ericn
ericn

Reputation: 13103

rxjava unit test onError not called

onCompleted is called instead, so weird

The method:

void load() {
    fetchData().subscribeOn(getIoScheduler())
            .observeOn(getMainThreadScheduler())
            .doOnError(throwable -> System.out.println("doOnError " + throwable))
            .subscribe(new Subscriber<MyObject>() {
                @Override
                public void onCompleted() {
                    System.out.println("onCompleted");
                }

                @Override
                public void onError(Throwable e) {
                    System.out.println("onError " + e);
                    handleError();
                }

                @Override
                public void onNext(MyObject myObject) {
                    handleSuccess(myObject);
                }
            });
 }

The test:

@Test
public void load() {
        Mockito.doReturn(Schedulers.immediate())
                .when(presenter)
                .getMainThreadScheduler();
        Mockito.doReturn(Schedulers.immediate())
                .when(presenter)
                .getIoScheduler();

        // a) Success case
MyObject object = Mockito.mock(MyObject.class);
        Mockito.doReturn(Observable.just(object))
                .when(presenter)
                .fetchData();

        presenter.load();

        Mockito.verify(presenter)
                .fetchData();
        Mockito.verify(presenter)
                .handleSuccess(object);
        Mockito.reset(presenter);

        // b) Error case
        Mockito.doReturn(Observable.error(new Exception("dummy exception"))).when(presenter)
                .fetchData();

        presenter.load();

        Mockito.verify(presenter)
                .handleError();
}

In the console, only onCompleted was printed out.

Interestingly, when I removed the code testing the success scenario, it works as expected:

@Test
    public void load() {
            Mockito.doReturn(Schedulers.immediate())
                    .when(presenter)
                    .getMainThreadScheduler();
            Mockito.doReturn(Schedulers.immediate())
                    .when(presenter)
                    .getIoScheduler();

            // b) Error case
            Mockito.doReturn(Observable.error(new Exception("dummy exception"))).when(presenter)
                    .fetchData();

            presenter.load();

            Mockito.verify(presenter)
                    .handleError();
    }

outputs:

onError

What am I missing here? Am I supposed to reset something before testing the error scenario?

I'm using RxJava 1.3.4

Upvotes: 1

Views: 3918

Answers (1)

R. Zag&#243;rski
R. Zag&#243;rski

Reputation: 20258

Probably the key here is:

Mockito.reset(presenter);

Calling that removes any mocking associated with threading, because it is set only once at the beginning of test method and mocking theads aren't set once again after reset.

To be honest testing success and error test cases should be two different test scenarios, what would allow for omitting resetting mocks.

The first scenario:

@Test
public void loadSuccess() {
    Mockito.doReturn(Schedulers.immediate())
            .when(presenter)
            .getMainThreadScheduler();
    Mockito.doReturn(Schedulers.immediate())
            .when(presenter)
            .getIoScheduler();
    MyObject object = Mockito.mock(MyObject.class);
    Mockito.doReturn(Observable.just(object))
            .when(presenter)
            .fetchData();

    presenter.load();

    Mockito.verify(presenter)
            .fetchData();
    Mockito.verify(presenter)
            .handleSuccess(object);
}

The second (error) scenario:

@Test
public void loadError() {
    Mockito.doReturn(Schedulers.immediate())
            .when(presenter)
            .getMainThreadScheduler();
    Mockito.doReturn(Schedulers.immediate())
            .when(presenter)
            .getIoScheduler();
    Mockito.doReturn(Observable.error(new Exception("dummy exception"))).when(presenter)
            .fetchData();

    presenter.load();

    Mockito.verify(presenter)
            .handleError();
}

Upvotes: 5

Related Questions