[英]Testing MVP Android with Retrofit included
I'm developing application based on MVP pattern using retrofit to perform networking. 我正在开发基于MVP模式的应用程序,使用改造来执行网络连接。 I want to unit test my presenter but it fails.
我想对我的演示者进行单元测试,但它失败了。
In my app dataView implements DataView
which is mocked by Mockito. 在我的应用程序中,dataView实现了由Mockito模拟的
DataView
。 In DataPresenter
in onViewCreated
method MyApi
instance is get from MyApplication
and it performs request. 在
DataPresenter
在onViewCreated
方法MyApi
实例是得到MyApplication
它执行请求。 Anonymous Subscriber<Data>
onNext calls showData(Data data)
on dataView
. 匿名
Subscriber<Data>
onNext调用showData(Data data)
上dataView
。 Unfortunatelly Mockito.verify(dataView).showData(data)
fails the test. 不幸的是,
Mockito.verify(dataView).showData(data)
未通过测试。 I mocked retrofit client by my self to response in deterministic way. 我嘲笑我的自我改造客户以确定的方式回应。
Code below: 代码如下:
public class DataFragment extends ProgressFragment implements DataView {
protected DataPresenter mDataPresenter;
//[...] initialization arguments boilerplate etc.
@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
mDataPresenter.onViewCreated(mId);
//[...]
}
@Override
public void startLoading() {
setContentShown(false);
}
@Override
public void stopLoading() {
setContentShown(true);
}
@Override
public void showData(Data data) {
setContentEmpty(false);
//[...] present data
}
@Override
public void showError() {
setContentEmpty(true);
setEmptyText(R.string.unknown_error);
}
}
In DataPresenter
: 在
DataPresenter
:
@Override
public void onViewCreated(long id) {
getView().startLoading();
MyApplication.getInstance().getMyApi().checkIn(User.getUser().getFormattedTokenForRequest(),
(int) id).observeOn(AndroidSchedulers.mainThread()).subscribeOn(Schedulers.io()).subscribe(new Subscriber<Data>() {
@Override
public void onCompleted() {
}
@Override
public void onError(Throwable e) {
getView().showError();
getView().stopLoading();
}
@Override
public void onNext(Data data) {
getView().showData(data);
getView().stopLoading();
}
});
;
}
My test case: 我的测试用例:
public static final String GOOD_RESPONSE = "[Data in JSON]"
public static final int GOOD_STATUS = 201;
@Mock
DataView mDataView;
@Mock
MyApplication app;
@Mock
SharedPreferencesManager mSharedPreferencesManager;
DataPresenter mDataPresenter;
@Before
public void setUp() throws Exception {
mDataPresenter = new DataPresenterImpl(mDataView);
MyApplication.setInstance(app);
Mockito.when(app.getSharedPreferencesManager()).thenReturn(mSharedPreferencesManager);
Mockito.when(mSharedPreferencesManager.getUser()).thenReturn(null);
}
@Test
public void testCase() throws Exception {
RestAdapter adapter = (new RestAdapter.Builder()).setEndpoint(URL)
.setClient(new MockClient(GOOD_RESPONSE, GOOD_STATUS))
.build();
Mockito.when(app.getMyApi()).thenReturn(adapter.create(MyApi.class));
mCheckInPresenter.onViewCreated(3);
Mockito.verify(checkInView).startLoading();
Mockito.verify(checkInView).showData(new Data());
}
Test fails on "Wanted but not invoked: dataView.showData(..." . 测试失败“通缉但未调用:dataView.showData(...”。
What is interesting Response execute()
is called in MockClient
but onNext(Data data)
in subscriber included in DataPresenterImpl
is not. 有趣的是
Response execute()
被调用MockClient
但onNext(Data data)
中包含的用户DataPresenterImpl
是没有的。 Any ideas? 有任何想法吗? I guess it is a problem with request being asynchronous.
我想这是请求异步的问题。
The problem is that the work is being sent to a different thread and mockito cant verify whats going on. 问题是工作被发送到另一个线程并且无法验证最新情况。 My solution to this would be to create a scheduler factory and mock it out and return the main thread for tests like these.
我的解决方案是创建一个调度程序工厂并将其模拟出来并返回主线程以进行这样的测试。 Something like:
就像是:
public class schedulerFactory {
public Scheduler io() {
return Schedulers.io();
}
//etc
}
then in your test you would write something like this: 然后在你的测试中你会写这样的东西:
@Mock SchedulerFactory factory
@Before
public void setUp() {
when(factory.io()).thenReturn(Schedulers.mainThread());
}
in general its a good idea to run all the code in the same thread for testing 一般来说,最好在同一个线程中运行所有代码进行测试
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.