2

下面的代码在 JUnit 环境下运行时不会崩溃。但是在应用程序中运行时它会崩溃。我可以在控制台中看到错误日志,但测试被标记为通过。

  @Test
  public void test() {
    Observable observable = Observable.error(new RuntimeException());
    observable.subscribe();
  }

所以,问题是:如何让它在 JUnit 中崩溃。因为是的,如果某些东西在应用程序中不起作用,那么如果它在单元测试中也不起作用,那是一件好事:)

在这个例子中,我可以直接访问 observable。但在我的真实测试中,我没有。真正的 observables 只是被测试类的内部细节。我能做的最多的事情就是注入调度程序或其他东西。

那么,如何在没有直接访问 observable 的情况下让它崩溃呢?

另外,我刚刚检查了这段代码也没有崩溃:

  @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();
      }
    });
  }
4

3 回答 3

6

根据 akarnokd,这是 RxJava2 特有的问题。

“这样的用法不再在 2.x 中同步抛出,而是在插件处理程序中出现错误。”

可以检查此代码是否引发了任何错误

public static List<Throwable> trackPluginErrors() {
    final List<Throwable> list = Collections.synchronizedList(new ArrayList<Throwable>());

    RxJavaPlugins.setErrorHandler(new Consumer<Throwable>() {
        @Override
        public void accept(Throwable t) {
            list.add(t);
        }
    });

    return list;
}
于 2016-12-20T14:03:04.350 回答
1

使用测试订阅者

    Observable observable = Observable.error(new RuntimeException());
    TestSubscriber testSubscriber = TestSubscriber.create();

    observable.subscribe(testSubscriber);

    testSubscriber.assertTerminalEvent();
    testSubscriber.assertError(RuntimeException.class);
于 2016-12-20T10:25:48.937 回答
1

我用来解决这个问题的一个小技巧是创建一个 JUnit4 TestRule 类,该类设置一个自定义 RxJava 错误处理程序,以便在发生未处理的 RxJava 错误时抛出:


/**
 * 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;
    }

}

在单元测试中:


public class YourRxTest {

    @Rule
    public RxErrorRule errorRule = new RxErrorRule();

    // ...
}
于 2021-11-16T22:11:57.433 回答