验证在RxJava订阅服务器的onNext中调用该方法

时间:2015-11-18 17:52:27

标签: android mockito rx-java

我有以下方法使用Retrofit服务接口从API获取一些数据,然后与view接口进行交互。

@Override
@VisibleForTesting
public void fetchPhotos(@Nullable PhotosService service, @Nullable Scheduler subscribeOn) {
    view.showLoading();

    Retrofit retrofit = new Retrofit.Builder()
            .baseUrl(Constants.PLACEHOLDER_API_BASE_URL)
            .addConverterFactory(GsonConverterFactory.create())
            .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
            .build();

    if (service == null) service = retrofit.create(PhotosService.class);
    if (subscribeOn == null) subscribeOn = Schedulers.newThread();

    service.listPhotos()
            .subscribeOn(subscribeOn)
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(photoList -> {
                Log.d(TAG, "got photos " + photoList.toString());
                view.unshowLoading();
            }, throwable -> {
                Log.d(TAG, "error " + throwable.toString());
                view.unshowLoading();
                view.displayError(throwable.toString(), v -> fetchPhotos());
            });
}

我想测试在onNext中调用view.unshowLoading()

这是我的测试:

@Test
public void viewUnshowsLoadingAfterFetchingPhotos() {

    PhotosListView view = Mockito.mock(PhotosListView.class);

    PhotosListPresenter presenter = new PhotosListPresenterImpl(view);

    presenter.fetchPhotos(() -> Observable.create(new Observable.OnSubscribe<List<Photo>>() {
        @Override
        public void call(Subscriber<? super List<Photo>> subscriber) {

            subscriber.onNext(new ArrayList<Photo>());

        }
    }), Schedulers.immediate());

    Mockito.verify(view).unshowLoading();


}

我明确传入Scheduler Schedulers.immediate()以确保在订阅主题上立即调用onNext()

当我通过我的方法调试时,onNext()未被调用。 我做错了什么或者我怎么能最好地测试这个?

编辑: This article让我了解了一些事情:

  

如果要更改执行操作的线程   你可以调用subscribeOn()。要回到主线程使用   observeOn(AndroidSchedulers.mainThread())。但请注意   每当您强制操作到特定线程时,它都会   总是订阅asynchronou s。

当我省略

        .subscribeOn(subscribeOn)
        .observeOn(AndroidSchedulers.mainThread())

部分,测试按预期工作。当没有传入调度程序时,我已将我的方法重新排列为observeOn()subscribeOn()中没有调用:

public void fetchPhotos(@Nullable PhotosService service, @Nullable Scheduler subscribeOn, @Nullable Scheduler observeOn) {
    view.showLoading();

    if (service == null) service = createService();

    Observable<List<Photo>> observable = service.listPhotos();

    if (subscribeOn != null) observable = observable.subscribeOn(subscribeOn);
    if (observeOn != null) observable = observable.observeOn(observeOn);

    observable.subscribe(photoList -> {
        Log.d(TAG, "got photos " + photoList.toString());
        view.unshowLoading();
    }, throwable -> {
        Log.d(TAG, "error " + throwable.toString());
        view.unshowLoading();
        view.displayError(throwable.toString(), v -> fetchPhotos());
    });
}

看起来有点笨拙,但有效。

任何想法仍然欢迎:)

1 个答案:

答案 0 :(得分:1)

第一个样本很好,只需注入ui调度程序并使用它。在您的测试中注入类似立即调度程序的东西,并在生产中注入Android ui调度程序。一般来说,最好不要在类中硬编码依赖项,而是注入它们。这是依赖注入可能有所帮助的案例之一。

关于subscribeOn的说明:您不需要在改装时使用它,因为改装将无论如何都会在默认线程上执行操作。还命名调度程序&#34; subscribeOn&#34;并且&#34;观察&#34;没有多大意义,因为您可能希望使用相同的调度程序传递给subscribeOn()observeOn()。给出更有意义的名字会更好,因为它们代表了什么,例如&#34; backgroundScheduler&#34;和&#34; uiScheduler&#34;