我正在尝试在我的应用程序中测试我的ViewModel,这里是构造函数:
@Inject
public SearchUserViewModel(@Named("searchUser") UseCase searchUserUseCase) {
this.searchUserUseCase = searchUserUseCase;
}
在我的测试中,我使用这样的模拟创建了一个SearchUserUseCase:
Observable error = Observable.error(new Throwable("Error"));
when(gitHubService.searchUser(MockFactory.TEST_USERNAME_ERROR)).thenReturn(error);
when(ObserverThread.getScheduler()).thenReturn(Schedulers.immediate());
when(SubscriberThread.getScheduler()).thenReturn(Schedulers.immediate());
searchUserUseCase = new SearchUserUseCase(gitHubService, SubscriberThread, ObserverThread);
在我的ViewModel类中,我有一个我要测试的代码片段:
public void onClickSearch(View view) {
loadUsers();
}
private void loadUsers() {
if (username == null) {
fragmentListener.showMessage("Enter a username");
} else {
showProgressIndicator(true);
searchUserUseCase.execute(new SearchUserSubscriber(), username);
}
}
private final class SearchUserSubscriber extends DefaultSubscriber<SearchResponse> {
@Override
public void onCompleted() {
showProgressIndicator(false);
}
@Override
public void onError(Throwable e) {
showProgressIndicator(false);
fragmentListener.showMessage("Error loading users");
}
@Override
public void onNext(SearchResponse searchResponse) {
List<User> users = searchResponse.getUsers();
if (users.isEmpty()) {
fragmentListener.showMessage("No users found");
} else {
fragmentListener.addUsers(users);
}
}
}
最后在我的测试中我有这个:
@Test
public void shouldDisplayErrorMessageIfErrorWhenLoadingUsers() {
SearchUserViewModel searchUserViewModel = new SearchUserViewModel(searchUserUseCase);
searchUserViewModel.setFragmentListener(mockFragmentListener);
searchUserViewModel.setUsername(MockFactory.TEST_USERNAME_ERROR);
searchUserViewModel.onClickSearch(view);
verify(mockFragmentListener).showMessage("Error loading users");
}
我从Mockito那里得到了这个错误:
Wanted but not invoked:
fragmentListener.showMessage(
"Error loading users"
);
我不确定这是否是一个很好的测试,但我想以某种方式测试SearchUserSubscriber。感谢
修改:我在此处找到了与此问题相似的问题:Can't verify mock method call from RxJava Subscriber(仍然没有回答)和此处:Verify interactions in rxjava subscribers。后一个问题类似,但不在单独的类中执行订阅者(这在SearchUserUseCase中发生)。
我也尝试过RobolectricGradleTestRunner而不是MockitoJunitRunner,并改为Schedulers.io()和AndroidSchedulers.mainThread(),但我仍然得到同样的错误。
尝试使用模拟SearchUserUseCase而不是GitHubService(感觉更干净),但我不确定如何以这种方式测试订阅者,因为它作为参数传递给UseCase中的void方法execute()。
public void execute(Subscriber useCaseSubscriber, String query) {
subscription = buildUseCase(query)
.observeOn(postExecutionThread.getScheduler())
.subscribeOn(threadExecutor.getScheduler())
.subscribe(useCaseSubscriber);
}
和buildUseCase()
@Override
public Observable buildUseCase(String username) throws NullPointerException {
if (username == null) {
throw new NullPointerException("Query must not be null");
}
return getGitHubService().searchUser(username);
}
答案 0 :(得分:1)
对我来说,最后添加Observable.Transformer<T, T>
如下:
void gatherData() {
service.doSomeMagic()
.compose(getSchedulerTransformer())
.subscribe(view::displayValue);
}
private <T> Observable.Transformer<T, T> getSchedulerTransformer() {
if (mTransformer == null) {
mTransformer = (Observable.Transformer<T, T>) observable -> observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
return mTransformer;
}
void setSchedulerTransformer(Observable.Transformer<Observable<?>, Observable<?>> transformer) {
mTransformer = transformer;
}
设置变形金刚。我刚刚通过了这个:
setSchedulerTransformer(observable -> {
if (observable instanceof Observable) {
Observable observable1 = (Observable) observable;
return observable1.subscribeOn(Schedulers.immediate())
.observeOn(Schedulers.immediate());
}
return null;
});
因此,只需在测试中添加@Before
方法并调用presenter.setSchedulerTransformer
,它就应该能够对此进行测试。如果您想了解更多详情,请查看this answer。
答案 1 :(得分:0)
如果您使用的是Mockito,则可以使用SearchUserSubscriber
获取ArgumentCaptor
,例如......
@Captor
private ArgumentCaptor<SearchUserSubscriber> subscriberCaptor;
private SearchUserSubscriber getSearchUserSubscriber() {
// TODO: ...set up the view model...
...
// Execute the code under test (making sure the line 'searchUserUseCase.execute(new SearchUserSubscriber(), username);' gets hit...)
viewModel.onClickSearch(view);
verify(searchUserUseCase).execute(subscriberCaptor.capture(), any(String.class));
return subscriberCaptor.getValue();
}
现在您可以拥有测试用例,例如......
@Test
public void shouldDoSomethingWithTheSubscriber() {
SearchUserSubscriber subscriber = getSearchUserSubscriber();
...
}