TestSubscribers allow you to avoid the work creating your own Subscriber or subscribe Action<?> to verify that certain values where delivered, how many there are, if the Observable completed, an exception was raised and a whole lot more.
This example just shows an assertion that the values 1,2,3 and 4 where passed into the Observable via onNext.
TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
ts.assertValues(1,2,3,4); // Success
assertValues
asserts that the count is correct. If you were to only pass some of the values, the assert would fail.
TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
ts.assertValues(1,2,3); // Fail
assertValues
uses the equals
method when doing asserts. This lets you easily test classes that are treated as data.
TestSubscriber<Object> ts = TestSubscriber.create();
Observable.just(new Object(), new Object()).subscribe(ts);
ts.assertValues(new Object(), new Object()); // Fail
This example shows a class that has a equals defined and asserting the values from the Observable.
public class Room {
public String floor;
public String number;
@Override
public boolean equals(Object o) {
if (o == this) {
return true;
}
if (o instanceof Room) {
Room that = (Room) o;
return (this.floor.equals(that.floor))
&& (this.number.equals(that.number));
}
return false;
}
}
TestSubscriber<Room> ts = TestSubscriber.create();
Observable.just(new Room("1", "10")).subscribe(ts);
ts.assertValue(new Room("1", "10"); // Success
Also take note that we use the shorter assertValue
because we only need to check for one item.
If need be you can also ask for all the events as a list.
TestSubscriber<Integer> ts = TestSubscriber.create();
Observable.just(1,2,3,4).subscribe(ts);
List<Integer> onNextEvents = ts.getOnNextEvents();
List<Throwable> onErrorEvents = ts.getOnErrorEvents();
List<Notification<Integer>> onCompletedEvents = ts.getOnCompletedEvents();
If you want to do more extensive tests on your events, you can combine getOnNextEvents
(or getOn*Events
) with your favorite assertion library:
Observable<Integer> obs = Observable.just(1,2,3,4)
.filter( x -> x % 2 == 0);
// note that we instanciate TestSubscriber via the constructor here
TestSubscriber<Integer> ts = new TestSubscriber();
obs.subscribe(ts);
// Note that we are not using Observable#forEach here
// but java.lang.Iterable#forEach.
// You should never use Observable#forEach unless you know
// exactly what you're doing
ts.getOnNextEvents()
.forEach( integer -> assertTrue(integer % 2 == 0));
Observable#error
You can make sure that the correct exception class is emitted:
Observable<Integer> obs = Observable.error(new Exception("I am a Teapot"));
TestSubscriber<Integer> ts = new TestSubscriber<>();
obs.subscribe(ts);
ts.assertError(Exception.class);
You can also make sure that the exact Exception was thrown:
Exception e = new Exception("I am a Teapot");
Observable<Integer> obs = Observable.error(e);
TestSubscriber<Integer> ts = new TestSubscriber<>();
obs.subscribe(ts);
ts.assertError(e);