How do I create a unit test that a certain side effect is done on doOnScubscribe
and doFinally
of an rxjava chain?
For Example:
Observable.requestSomeValueFromWeb()
.doOnSubscribe(() -> showLoading = true)
.doFinally(() -> showLoading = false)
.subscribe(result -> doSomething(result), error -> doErrorHandling(error));
How do I test in the scenario above that the showLoading
was set to true on subscribe and false when the observable was disposed?
TestSubscriber<WebServiceResponse> loginRequestSubscriber = new TestSubscriber<>();
clientLoginViewModel.requestLogin().subscribe(loginRequestSubscriber);
// check that showLoading was true when webservice was called
assertEquals(true, showLoading);
// check that showLoading was false when webservice was finished
assertEquals(false, showLoading);
loginRequestSubscriber.assertSubscribed();
If I understand correctly, your Object Under Test is the
ClientLoginViewModel
, so I'm trying to work from there. Let me know if I'm mistaken and I can revisit my answer:
The classes from your system:
interface WebServiceResponse { } // We don't care about this here
interface Network {
// This is whatever interacts with the Network, and we'll mock it out
Single<WebServiceResponse> requestSomeValue();
}
// The class we are testing
class ClientLoginViewModel {
final Network mNetwork;
// This is the field we want to check... you probably want to make it
// private and have accessors for it
boolean showLoading;
// This allows dependency injection, so we can mock :)
ClientLoginViewModel(final Network network) {
mNetwork = network;
}
// The actual method to test!
Single<WebServiceResponse> requestLogin() {
return mNetwork.requestSomeValue()
.doOnSubscribe(disposable -> showLoading = true)
.doFinally(() -> showLoading = false);
}
}
And now the test!!!
class ClientLoginViewModelTest {
@Test
public void testLoading() {
final Network network = mock(Network.class);
final WebServiceResponse response = mock(WebServiceResponse.class);
// This is the trick! We'll use it to allow us to assert anything
// before the stream is done
final PublishSubject<Boolean> delayer = PublishSubject.create();
when(network.requestSomeValue())
.thenReturn(
Single.just(response).delaySubscription(publishSubject)
);
final ClientLoginViewModel clientLoginViewModel = new ClientLoginViewModel(network);
clientLoginViewModel
.requestLogin()
.test();
// check that showLoading was true when webservice was called
assertEquals(true, clientLoginViewModel.showLoading);
// now let the response from the Network continue
publishSubject.onComplete();
// check that showLoading was false when webservice was finished
assertEquals(false, clientLoginViewModel.showLoading);
}
}