0

I'm trying to debug the inner success callback of an RxJava Subscription object and verify certain methods inside that get called with the correct argument(s). I read up some about Captors and though maybe that's the way to go but was unable to find an example that matched my needs.

I'm unit testing with: Mockito and JUnit

// OrderHistoryPresenterImpl presenter;
public void loadOrderHistory(final int offset, final int limit) {
    mCompositeSubscription.add(useCase.getOrderHistory(offset, limit)
            .doOnError(throwable -> Timber.e(throwable, "Error"))
            .observeOn(AndroidSchedulers.mainThread())
            .subscribe(new Subscriber<ListOfOrders>() {
                @Override
                public void onCompleted() {}

                @Override
                public void onError(Throwable e) {}

                @Override
                public void onNext(ListOfOrders listOfOrders) {
                    //
                    // I would like to verify the calls in this method
                    //
                    user.setTryoutCountActive(listOfOrders.getActiveTryoutsCount());

                    getView().addOrdersToView(listOfOrders);

                    mCompositeSubscription.clear();
                }
            })
    );
}

And here are the tests I'm trying to test it with

@RunWith(MockitoJUnitRunner.class)
public class OrderHistoryPresenterTest {
    // Boiler plate Dagger 2 setup + variable declarations

    private ListOfOrders response;
    private ListOfOrders spyListOfOrders;
    private OrderHistoryPresenterImpl presenter;
    @Mock private OrderHistoryUseCaseImpl useCase;

    @Before
    public void setUp() throws FileNotFoundException {
        // Setup + dagger 2 setup…

        response = Utils.fromJson(gson, this, "OrderHistory.json", type);
        spyListOfOrders = spy(response);

        presenter = new OrderHistoryPresenterImpl(app, useCase, user);

        when(useCase.getOrderHistory(MOCK_USER_ACCESS_TOKEN)).thenReturn(Observable.just(spyListOfOrders));
    }

    @After
    public void tearDown() {…}

    @Test
    public void shouldGetOrderAndCall_addOrdersToView_OnActivity() {
        presenter.loadOrderHistory(MOCK_OFFSET, MOCK_LIMIT);

        // works…
        verify(useCase, times(1)).getOrderHistory(MOCK_USER_ACCESS_TOKEN);

        // This fails because it gets called right away because it's async - what to do?
        verify(view, times(1)).addOrdersToView(spyListOfOrders);
    }
}

So as you can see I don't know how to test the inner Subscriber<ListOfOrders> callback methods. Any help would be greatly appreciated!

Maruf
  • 890
  • 3
  • 10
  • 21
  • So if you want to test if your "Observable" works, you can use TestSubscriber and do assertions on top of it. Ref: http://reactivex.io/RxJava/javadoc/rx/observers/TestSubscriber.html. But if you want to test the Subscriber methods like onNext, then pass this guy with your `loadOrderHistory` (instead of creating a new one) so that you can Mock this in your tests. – Bharath Mg Sep 15 '16 at 17:17
  • Checkout [RxJavaDebug](https://github.com/ReactiveX/RxJavaDebug). It may help. – Chad Bingham Sep 15 '16 at 17:31

1 Answers1

1

Let's say if you rewrite your method like this,

// OrderHistoryPresenterImpl presenter;
public void loadOrderHistory(final int offset, final int limit) {
  mCompositeSubscription.add(useCase.getOrderHistory(offset, limit)
        .doOnError(throwable -> Timber.e(throwable, "Error"))
        .observeOn(AndroidSchedulers.mainThread())
        .subscribe(new Subscriber<ListOfOrders>() {
            @Override
            public void onCompleted() {}

            @Override
            public void onError(Throwable e) {}

            @Override
            public void onNext(ListOfOrders listOfOrders) {
               load(listOfOrders)
            }
        })
   );
 }

 void loadOrders(ListOfOrders list) {
     // I would like to verify the calls in this method
     user.setTryoutCountActive(listOfOrders.getActiveTryoutsCount());

     getView().addOrdersToView(listOfOrders);

     mCompositeSubscription.clear();
 }

Now test this loadOrders method separately. Because all it cares about is getting a list of orders to process. It can come from anywhere (not only observable).

You can unit test this method now.

If you want to test Observable, then use TestSubscriber to see if you are actually getting a list of orders from Observable. Ref : https://reactivex.io/RxJava/javadoc/rx/observers/TestSubscriber.html‌​

Bharath Mg
  • 1,117
  • 1
  • 9
  • 18
  • One problem now is that the only way I can test loadOrders is by making it public even though I would prefer to keep a method like this private. Any clean work arounds while still keeping the test files separately packaged? – Maruf Sep 16 '16 at 15:32
  • Hey for testing private methods, you can use PowerMock which uses JAVA Reflection to give access. But it is generally not recommended to test private methods. http://stackoverflow.com/questions/34571/how-to-test-a-class-that-has-private-methods-fields-or-inner-classes – Bharath Mg Sep 16 '16 at 17:09