在Android中的MVP Presenter中对RxJava进行单元测试 [英] Unit testing RxJava in MVP presenter in android
问题描述
我是TDD的新手.同样是MVP和Rxjava的新功能.我只是深入研究,这是值得的.但是我停留在测试部分.我了解单元测试的基础.一开始对我来说有点困难.但是我被困在这里,那么如何测试演示者呢?
I am new to TDD. Also new to MVP and Rxjava. I just dive into it and It is worth it. But I stuck at the testing part. I understand the basis of unit testing. It is a little bit difficult for me in beginning. But I stuck here and So how can test the presenter?
这是Presenter类-
Here is the Presenter class -
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类-
Here is the RxJavaService class -
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");
}
});
}
}
这是我被困的Test类-
Here is the Test class where I am stuck-
@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() {
}
}
推荐答案
第一件事
- 如果您要使用TDD,就永远不会遇到您所描述的情况.在TDD中,您以失败的测试开始,然后立即编写实现.因此,您的问题更多的是测试,然后是TDD.
- 我建议您切换到RxJava2,因为RxJava1将于3月31日到期.
- 让我感到奇怪的是,
RxJavaService
将API从发布/订阅更改为回调.为什么不一直使用rx API进行演示?
- If you're into TDD, you'd never get into the situation you described. In TDD you start with a failing test, and just then go write the implementation. So your question is much more about testing then TDD.
- I would recommend switching to RxJava2, as RxJava1 reaches End Of Life on March 31.
- Look strange to me that
RxJavaService
changes the API from publish/subscribe to callbacks. Why not stick with rx API all the way to presenter?
使用模拟的RxJavaService进行测试
如果您要使用测试中的设置完成编写测试的过程,它将看起来像这样:
Test with mocked RxJavaService
If you'd like to finish writing the test with the setup you have in the test, it would look something like this:
@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
来摆脱丑陋的代码,而滚动自己的手写模拟,它将存储回调并将其提供给测试.
You can get rid of the ugly code by not using Mockito to mock RxJavaService
, but rather roll you own hand-written mock, which would store the callback and provide it to the test.
但是,我建议使用另一种方法.
However, I'd recommend a different approach.
如果我们只嘲笑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));
}
}
这篇关于在Android中的MVP Presenter中对RxJava进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!