如何模拟采用回调对象和调用者使用回调委托结果的方法
How to mock a method that takes callback object and invoker use callback to delegate result
如何模拟一个采用回调对象的方法,该方法的调用者使用它将结果委托给其他回调。在我的场景中,我正在从中创建 Rx Single。
1. RecentDataModel.java
public class RecentDataModel {
public void getRecentData(RecentDataAdapter recentDataAdapter) {
// Get data from database
// Invoke if success
recentDataAdapter.onSuccess()
// Invoke if error
recentDataAdapter.onError()
}
}
2。 RecentDataAdapter.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");
}
}
注:
无法访问 RecentDataModel,因此无法引入新方法,例如:List<String> getRecentData();
尽管方法 ResentPresenter.getRecentsSingle() 没有执行任何业务逻辑。但是它与 class 中的其他方法连接以产生输出。所以模拟 RecentDataModel 是必要的。
测试在后续行 "verify(onNextListener, timeout(5000)).call(listCaptor.capture());"
中失败,因为在模拟时我提供了 any(RecentDataAdapter.class)
,因此 singleSubscriber.onSuccess(keywordList);
永远不会被调用。
问题是您没有在适配器上调用回调。由于永远不会调用回调,因此永远不会调用 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));
如何模拟一个采用回调对象的方法,该方法的调用者使用它将结果委托给其他回调。在我的场景中,我正在从中创建 Rx Single。
1. RecentDataModel.java
public class RecentDataModel {
public void getRecentData(RecentDataAdapter recentDataAdapter) {
// Get data from database
// Invoke if success
recentDataAdapter.onSuccess()
// Invoke if error
recentDataAdapter.onError()
}
}
2。 RecentDataAdapter.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");
}
}
注:
无法访问 RecentDataModel,因此无法引入新方法,例如:
List<String> getRecentData();
尽管方法 ResentPresenter.getRecentsSingle() 没有执行任何业务逻辑。但是它与 class 中的其他方法连接以产生输出。所以模拟 RecentDataModel 是必要的。
测试在后续行
"verify(onNextListener, timeout(5000)).call(listCaptor.capture());"
中失败,因为在模拟时我提供了any(RecentDataAdapter.class)
,因此singleSubscriber.onSuccess(keywordList);
永远不会被调用。
问题是您没有在适配器上调用回调。由于永远不会调用回调,因此永远不会调用 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));