简体   繁体   English

测试包含Retrofit的MVP Android

[英]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. DataPresenteronViewCreated方法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()被调用MockClientonNext(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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM