Checking communication between rxjava subscribers
To depict a situation in an MVP template where your presenter subscribes to a service that returns an observer:
public void gatherData(){
service.doSomeMagic()
.observeOn(Schedulers.io())
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(new TheSubscriber());
}
Now the class TheSubscriber
calls the onNext
method from the view, for example:
@Override public void onNext(ReturnValue value) {
view.displayWhatever(value);
}
Now, in my unit test, I would like to check that when the method is called gatherData()
in a non-error situation, the view method is displayWhatever(value)
called.
Question :
Is there a clean way to do this?
Background
- I use mockito to test interactions and of course, much more.
- The dagger enters the entire presenter except
TheSubscriber
What I have tried :
- Introduce a subscriber and make fun of him in tests. I find it a little messy because if I want to change the way the presenter interacts with a service (say, not Rx), I need to change a lot of tests and code.
- Fool the whole service. It wasn't that bad, but I had a lot of methods to mock and I didn't quite get to what I wanted.
- Looked on the internet but no one seems to have a straight forward way to do this.
thanks for the help
source to share
Assuming you are using interfaces for service
and in a view
similar manner:
class Presenter{
Service service;
View view;
Presenter(Service service){
this.service = service;
}
void bindView(View view){
this.view = view;
}
void gatherData(){
service.doSomeMagic()
.observeOn(Schedulers.io())
.subscribeOn(AndroidSchedulers.mainThread())
.subscribe(view::displayValue);
}
}
Then you can mock to monitor and test the behavior:
@Test void assert_that_displayValue_is_called(){
Service service = mock(Service.class);
View view = mock(View.class);
when(service.doSomeMagic()).thenReturn(Observable.just("myvalue"));
Presenter presenter = new Presenter(service);
presenter.bindView(view);
presenter.gatherData();
verify(view).displayValue("myvalue");
}
source to share
I know its quite late, but can it help someone because I have been looking for quite a while for a solution to your question: D
For me it worked out to add Observable.Transformer<T, T>
as follows:
void gatherData() {
service.doSomeMagic()
.compose(getSchedulerTransformer())
.subscribe(view::displayValue);
}
private <T> Observable.Transformer<T, T> getSchedulerTransformer() {
if (mTransformer == null) {
mTransformer = (Observable.Transformer<T, T>) observable -> observable.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
return mTransformer;
}
void setSchedulerTransformer(Observable.Transformer<Observable<?>, Observable<?>> transformer) {
mTransformer = transformer;
}
And to install Transformer just I just passed this:
setSchedulerTransformer(observable -> {
if (observable instanceof Observable) {
Observable observable1 = (Observable) observable;
return observable1.subscribeOn(Schedulers.immediate())
.observeOn(Schedulers.immediate());
}
return null;
});
So just add a method @Before
to your test and call presenter.setSchedulerTransformer
and it should check it :)
hope this helps and is somehow clear: D
source to share