【问题标题】:How to mock a method that takes callback object and invoker use callback to delegate result如何模拟采用回调对象和调用者使用回调委托结果的方法
【发布时间】:2016-06-24 11:11:05
【问题描述】:

如何模拟一个接受回调对象的方法,并且该方法的调用者使用它来将结果委托给其他回调。在我的场景中,我正在从中创建 Rx Single。

1.最近的DataModel.java

public class RecentDataModel {

public void getRecentData(RecentDataAdapter recentDataAdapter) {
    // Get data from database
    // Invoke if success
    recentDataAdapter.onSuccess()
    // Invoke if error
    recentDataAdapter.onError()

}
}

2。最近的DataAdapter.java

public class RecentDataAdapter {
    onSuccess(List<String> recents);
    onError();
}

3.最近的演讲者

public class RecentPresenter {
public Single<List<String>> getRecentsSingle() {
    return Single.create(new Single.OnSubscribe<List<String>>() {
            @Override
            public void call(final SingleSubscriber<? super List<String>> singleSubscriber) {
                mRecentDataModel.getRecentData(new RecentDataAdapter() {
                    @Override
                    public void onSuccess(List<String> keywordList) {
                        singleSubscriber.onSuccess(keywordList);
                    }
                });
            }
        });
}
}

4.最近的测试用例

public class RecentPresenterTest {

    @Mock
    RecentDataModel recentModel;

    @Test
    public void testLoadRecent() {
        doAnswer(new Answer() {
            @Override
            public List<String> answer(InvocationOnMock invocation) throws Throwable {
                List<String> recents = new ArrayList<>();
                recents.add("Recent1");
        recents.add("Recent2");
                return recents;
            }
        }).when(recentModel).getRecentData(any(RecentDataAdapter.class));

        RecentPresenter recentProvider = new RecentPresenter(null, null, prefModel);

        Action1 onNextListener = mock(Action1.class);

        recentProvider.getRecentsSingle.subscribe(onNextListener);

        ArgumentCaptor<List<String>> listCaptor = ArgumentCaptor.forClass((Class) List.class);

        verify(onNextListener, timeout(5000)).call(listCaptor.capture());
        assertNotNull(listCaptor.getValue());
        assertEquals(listCaptor.getValue().get(0), "Recent1");
    }

}

注意:

  1. 无法访问 RecentDataModel,因此无法引入新方法,例如:List&lt;String&gt; getRecentData();

  2. 虽然方法 ResentPresenter.getRecentsSingle() 没有做任何业务逻辑。但它与类中的其他方法连接以产生输出。所以模拟RecentDataModel是必要的。

  3. "verify(onNextListener, timeout(5000)).call(listCaptor.capture());" 后面的行中测试失败,因为在模拟时我提供了any(RecentDataAdapter.class),因此singleSubscriber.onSuccess(keywordList); 永远不会被调用。

【问题讨论】:

  • 如果需要更多信息,请告诉我。

标签: android mockito junit4 rx-java powermock


【解决方案1】:

问题是您没有在适配器上调用回调。由于从不调用回调,因此从不调用 Single.success。所以Single 不会被通知到发出的列表。然后你的验证超时。

要解决这个问题,你必须在你的 mock 中调用 onSuccess 回调方法:

  doAnswer(new Answer() {
        @Override
        public Void answer(InvocationOnMock invocation) throws Throwable {
            List<String> recents = new ArrayList<>();
            recents.add("Recent1");
            recents.add("Recent2");
            invocation.getArguments()[0].onSuccess(recents);
            return null;
        }
 }).when(recentModel).getRecentData(any(RecentDataAdapter.class));

【讨论】:

  • 谢谢@dwursteisen。我是否需要在“SingleSubscriber>”中键入强制转换“invocation.getArguments()[0]”才能调用 onSuccess()。请回复
  • 感谢 dwursteisen 为我所做的这样的工作:((RecentDataAdapter) invocation.getArguments()[0]).onSuccess(recents);。非常感谢你。
猜你喜欢
  • 1970-01-01
  • 2023-01-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-11
  • 2011-01-19
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多