使用DisposableObserver测试Presenter

时间:2018-03-26 16:16:22

标签: android unit-testing mockito clean-architecture

我正在开发一个Android应用程序,试图遵循Clean Architecture / MVP指南。

我目前正在为我的演示者进行单元测试,但我仍然坚持调用Interactor / UseCase,它将DisposableObserver作为参数。

我想测试的是当交互器调用OnNext或OnError时调用正确的行为(隐藏/显示加载指示符......)。

我不知道如何在我的用例中“模拟”Observable的行为,因为它是在使用受保护的方法调用execute()方法时构建的。

以下是代码的一些部分:

演示

@ConfigPersistent
public class ContentPresenter extends BasePresenter<ContentContract.View> implements ContentContract.Presenter {

    @Inject
    GetContent mGetContentUseCase;

    @Inject
    ContentViewModelMapper mContentViewModelMapper;

    @Inject
    public ContentPresenter() {
    }

    @Override
    public void fetchContent(long contentId) {
        getMvpView().showProgress();
        mGetContentUseCase.execute(contentId, new ContentObserver());
    }

    private final class ContentObserver extends DisposableObserver<Content> {
        @Override
        public void onNext(Content content) {
            getMvpView().hideProgress();
            getMvpView().showContentInfo(mContentViewModelMapper.map2(content));
        }

        @Override
        public void onError(Throwable e) {
            getMvpView().hideProgress();
            Timber.e(e.getMessage());
        }

        @Override
        public void onComplete() {
            getMvpView().hideProgress();
        }
    }
}

交互器/用例

public class GetContent extends UseCaseObservableWithParameter<Long, Content, Repository> {

    @Inject
    public GetContent(Repository repository,
                         @Named("Thread") Scheduler threadScheduler,
                         @Named("PostExecution") Scheduler postExecutionScheduler) {
        super(repository, threadScheduler, postExecutionScheduler);
    }

    @Override
    protected Observable<Content> buildObservable(Long id) {
        return repository.getContentById(id);
    }
}

BaseUseCase

public abstract class UseCaseObservableWithParameter<REQUEST_DATA, RESPONSE_DATA, REPOSITORY> extends UseCase<Observable<RESPONSE_DATA>, REQUEST_DATA, REPOSITORY> {

    public UseCaseObservableWithParameter(REPOSITORY repository, Scheduler threadScheduler, Scheduler postExecutionScheduler) {
        super(repository, threadScheduler, postExecutionScheduler);
    }

    protected abstract Observable<RESPONSE_DATA> buildObservable(REQUEST_DATA requestData);

    public void execute(REQUEST_DATA requestData, DisposableObserver<RESPONSE_DATA> useCaseSubscriber) {
        this.disposable.clear();
        this.disposable.add(
                this.buildObservable(requestData)
                        .subscribeOn(threadScheduler)
                        .observeOn(postExecutionScheduler)
                        .subscribeWith(useCaseSubscriber)
        );
    }
}

1 个答案:

答案 0 :(得分:0)

经过一夜安眠之后,我就想到了这一点:

@Test
@SuppressWarnings("unchecked")
public void testShowContents() {
    doAnswer((i) -> {
        // Do stuff with i.getArguments() here
        DisposableObserver<Content> d = i.getArgument(1);
        Observable.just(mock(Content.class)).subscribeWith(d);
        return null;
    })
            .when(mGetContentUseCase)
            .execute(eq(AppTestData.TEST_LONG_ID_1), any(DisposableObserver.class));

    contentPresenter.fetchContent(AppTestData.TEST_LONG_ID_1);

    Mockito.verify(view, Mockito.times(1)).showContentInfo(Mockito.any());

    InOrder orderVerifier = Mockito.inOrder(view);
    orderVerifier.verify(view).showProgress();
    orderVerifier.verify(view).hideProgress();
    orderVerifier.verify(view).showContentInfo(any());
}

@Test
@SuppressWarnings("unchecked")
public void testShowContentsError() {
    doAnswer((i) -> {
        // Do stuff with i.getArguments() here
        DisposableObserver<Content> d = i.getArgument(1);
        Observable.<Content>error(new Throwable()).subscribeWith(d);
        return null;
    })
            .when(mGetContentUseCase)
            .execute(eq(AppTestData.TEST_LONG_ID_1), any(DisposableObserver.class));

    contentPresenter.fetchContent(AppTestData.TEST_LONG_ID_1);

    Mockito.verify(view, Mockito.times(1)).showErrorMessage(Mockito.any());

    InOrder orderVerifier = Mockito.inOrder(view);
    orderVerifier.verify(view).showProgress();
    orderVerifier.verify(view).hideProgress();
    orderVerifier.verify(view).showErrorMessage(any());
}