The code below won't crash when running in JUnit environment. But it crashes when running in the app. I can see error logs in the console, but tests are marked as passed.
@Test
public void test() {
Observable observable = Observable.error(new RuntimeException());
observable.subscribe();
}
So, the question is: how to make it crash in JUnit. Because yeah, if something doesn't work in the app it's a good thing if it doesn't work in the unit tests also :)
And in this example I have direct access to the observable. But in my real tests I don't have that. Real observables are just internal details of classes that being tested. The most thing I can to do is to inject schedulers or something.
So, how to make it crash without having direct access to the observable?
Also, I've just checked this code doesn't crash either:
@Test
public void test() {
Observable observable = Observable.error(new RuntimeException());
observable.subscribe(new Consumer() {
@Override
public void accept(Object o) throws Exception {
throw new RuntimeException();
}
}, new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) throws Exception {
throw new RuntimeException();
}
});
}
A small trick I use to tackle this problem, is creating a JUnit4 TestRule class that setups a custom RxJava error handler so it can throw when an unhandled RxJava error occurs:
/**
* A rule that detects RxJava silent errors and reports them to JUnit
(by throwing them).
*/
public class RxErrorRule implements TestRule {
@Override
public Statement apply(Statement base, Description description) {
return new Statement() {
@Override
public void evaluate() throws Throwable {
Consumer<? super Throwable> previous = RxJavaPlugins.getErrorHandler();
AtomicReference<Throwable> result = setupErrorHandler();
try {
base.evaluate();
} finally {
RxJavaPlugins.setErrorHandler(previous);
}
if (result.get() != null) {
throw result.get();
}
}
};
}
private AtomicReference<Throwable> setupErrorHandler() {
AtomicReference<Throwable> result = new AtomicReference<>();
RxJavaPlugins.setErrorHandler(new Consumer<Throwable>() {
@Override
public void accept(Throwable throwable) {
result.set(throwable);
}
});
return result;
}
}
And in the unit test:
public class YourRxTest {
@Rule
public RxErrorRule errorRule = new RxErrorRule();
// ...
}