我是TDD的新手。也是MVP和Rxjava的新手。我只是潜入它,这是值得的。但我坚持在测试部分。我理解单元测试的基础。这对我来说有点困难。但我坚持到这里,那么如何测试主持人呢?
这是Presenter类 -
public class NewsPresenter {
private final RxjavaService service;
private final MainView view;
private CompositeSubscription subscriptions;
public NewsPresenter(RxjavaService service, MainView view) {
this.service = service;
this.view = view;
subscriptions = new CompositeSubscription();
}
public void getNewsList(String urlQ){
view.showWait();
Subscription subscription = service.getNews(urlQ ,new RxjavaService.GetNewsCallback() {
@Override
public void onSuccess(Articles articles) {
view.removeWait();
view.getNewsListSuccess(articles);
}
@Override
public void onError(NetworkError networkError) {
view.removeWait();
view.onFailure(networkError.getAppErrorMessage());
Log.i("huh",networkError.getMessage());
}
});
subscriptions.add(subscription);
}
public void onStop(){
subscriptions.unsubscribe();
}
}
这是视图界面 -
public interface MainView {
void showWait();
void removeWait();
void onFailure(String appErrorMessage);
void getNewsListSuccess(Articles articles);
}
这是RxJavaService类 -
public class RxjavaService {
private final NewsRestService newsRestService;
public RxjavaService(NewsRestService newsRestService) {
this.newsRestService = newsRestService;
}
public interface GetNewsCallback {
void onSuccess(Articles articles);
void onError(NetworkError networkError);
}
public Subscription getNews(String q, final GetNewsCallback getNewsCallback) {
Log.i("stuck","service called");
return newsRestService.getNewsBySearch(q,"8dca7dea475e41e49518b2c61131e118",100)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.onErrorResumeNext(new Func1<Throwable, Observable<? extends Articles>>() {
@Override
public Observable<? extends Articles> call(Throwable throwable) {
return Observable.error(throwable);
}
})
.subscribe(new Subscriber<Articles>() {
@Override
public void onCompleted() {
Log.i("stuck","complete");
}
@Override
public void onError(Throwable e) {
getNewsCallback.onError(new NetworkError(e));
Log.i("stuck",e.getMessage());
}
@Override
public void onNext(Articles articles) {
getNewsCallback.onSuccess(articles);
Log.i("stuck","Onnext");
}
});
}
}
这是我被困的测试课 -
@RunWith(MockitoJUnitRunner.class)
public class NewsListTest {
private NewsPresenter newsPresenter;
@Mock
private RxjavaService rxjavaService;
@Mock
private MainView mainView;
@Before
public void setUp() throws Exception {
MockitoAnnotations.initMocks(this);
newsPresenter = new NewsPresenter(rxjavaService,mainView);
}
@After
public void tearDown() throws Exception {
mainView = null;
newsPresenter.onStop();
}
@Test
public void Testing_The_Result() {
}
}
答案 0 :(得分:0)
RxJavaService
将API从发布/订阅更改为回调。为什么不坚持使用rx API一直到演示者?如果您希望使用测试中的设置完成测试,则看起来像这样:
@Test
public void Testing_The_Result() {
final RxjavaService.GetNewsCallback[] callback = new RxjavaService.GetNewsCallback[1];
Mockito.when(rxjavaService.getNews(ArgumentMatchers.anyString(), ArgumentMatchers.any(RxjavaService.GetNewsCallback.class))).thenAnswer(new Answer<Subscription>() {
public Subscription answer(InvocationOnMock invocationOnMock) {
callback[0] = invocationOnMock.getArgument(1);
return mock(Subscription.class);
}
});
newsPresenter.getNewsList("some url");
Articles articles = new Articles();
callback[0].onSuccess(articles);
verify(mainView).removeWait();
verify(mainView).getNewsListSuccess(articles);
}
你可以通过不使用Mockito模拟RxJavaService
来摆脱丑陋的代码,而是滚动你自己的手写模拟,它会存储回调并将其提供给测试。
但是,我建议采用不同的方法。
如果我们只嘲笑NewsRestService
,我会说它更有意义并提供更好的测试:
@RunWith(MockitoJUnitRunner.class)
public class NewsList2Test {
private NewsPresenter newsPresenter;
@Mock
private MainView mainView;
@Mock
private NewsRestService newsRestService;
@Before
public void setUp() {
newsPresenter = new NewsPresenter(new RxjavaService(newsRestService), mainView);
}
@Test
public void show_success_in_view_when_there_are_articles() {
when(newsRestService.getNewsBySearch(eq("some url"), anyString(), anyInt()))
.thenReturn(Observable.just(new Articles()));
newsPresenter.getNewsList("some url");
verify(mainView).removeWait();
verify(mainView).getNewsListSuccess(any(Articles.class));
}
}