NiceErrorOperator { @Nonnull public static <T> Observable.Operator<T, T> niceErrorOperator(@Nullable final String message) { final StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace(); return niceErrorOperator(message, stackTraceElements); }  @Nonnull static Observable.Operator<T, T> niceErrorOperator(@Nullable final String message); @Nonnull static Observable.Operator<T, T> niceErrorOperator(
            @Nullable final String message,
            @Nullable final StackTraceElement[] stackTraceElements); @Nonnull static Observable.Operator<T, T> niceErrorOperator();  }
@Test public void testWhenErrorIsReturned_niceErrorIsCaptured() throws Exception { final TestObserver<Object> observer = new TestObserver<>(); Observable.error(new IOException("error")) .lift(NiceErrorOperator.niceErrorOperator("Some error")) .subscribe(observer); final List<Throwable> errors = observer.getOnErrorEvents(); assert_().that(errors) .hasSize(1); assert_().that(errors.get(0)) .isInstanceOf(NiceErrorOperator.NiceRxError.class); }
@Test public void testErrorWithMessage_messageIsPropagated() throws Exception { final TestObserver<Object> observer = new TestObserver<>(); Observable.error(new IOException("error")) .lift(NiceErrorOperator.niceErrorOperator("Some error")) .subscribe(observer); final NiceErrorOperator.NiceRxError error = (NiceErrorOperator.NiceRxError) observer .getOnErrorEvents().get(0); assert_().that(error.userMessage()) .isEqualTo("Some error"); }
@Test public void testErrorWithoutMessage_hasStackTrace() throws Exception { final TestObserver<Object> observer = new TestObserver<>(); Observable.error(new IOException("error")) .lift(NiceErrorOperator.niceErrorOperator()) .subscribe(observer); final NiceErrorOperator.NiceRxError error = (NiceErrorOperator.NiceRxError) observer .getOnErrorEvents().get(0); assert_().that(error.getMessage()) .contains("NiceErrorOperatorTest"); final StackTraceElement[] trace = error.stackTraceElements(); assert_().that(trace) .isNotEmpty(); assert_().that(trace[2].getClassName()) .contains("NiceErrorOperatorTest"); }
@Test public void testErrorOccur_RootCauseIsPropagated() throws Exception { final TestObserver<Object> observer = new TestObserver<>(); final IOException e = new IOException("error"); Observable.error(e) .lift(NiceErrorOperator.niceErrorOperator("Some error")) .subscribe(observer); assert_().that(observer.getOnErrorEvents().get(0).getCause()) .isEqualTo(e); }
@Test public void testOnNextIsPropagated() throws Exception { final TestObserver<Object> observer = new TestObserver<>(); Observable.just("a") .lift(NiceErrorOperator.niceErrorOperator("Some error")) .subscribe(observer); assert_().that(observer.getOnNextEvents()) .containsExactly("a"); assert_().that(observer.getOnErrorEvents()) .isEmpty(); }
@Test public void testOnCompletedIsPropagated() throws Exception { final TestObserver<Object> observer = new TestObserver<>(); Observable.empty() .lift(NiceErrorOperator.niceErrorOperator("Some error")) .subscribe(observer); assert_().that(observer.getOnCompletedEvents()) .hasSize(1); assert_().that(observer.getOnErrorEvents()) .isEmpty(); }