如何测试该observable在RxJava中使用正确的调度程序?

时间:2016-04-08 13:50:58

标签: unit-testing mockito rx-java

我有以下课程(简化):

public class Usecase<T> {
    private final Observable<T> get;
    private final Scheduler observeScheduler;

    public Usecase(Observable<T> get, Scheduler observeScheduler) {
        this.get = get;
        this.observeScheduler = observeScheduler;
    }

    public Observable<T> execute() {
        return get.subscribeOn(Schedulers.io()).observeOn(observeScheduler);
    }
}

我正在为它编写单元测试。如何测试使用正确的值调用subscribeOnobserveOn

我尝试以下方法:

    Observable<String> observable = mock(Observable.class);
    Usecase<String> usecase = new Usecase(observable, Schedulers.computation());
    usecase.execute();

    verify(observable).subscribeOn(Schedulers.computation()); // should fail here, but passes
    verify(observable).observeOn(Schedulers.computation());   // should pass, but fails: Missing method call for verify(mock) here

以上失败(我认为),因为subscribeOnobserveOnfinal方法。那么可能还有其他方法可以确保observable使用正确的调度程序吗?

2 个答案:

答案 0 :(得分:4)

There is a way间接访问observable正在运行和被观察的两个线程,这意味着您实际上可以验证Observable使用正确的调度程序。

我们仅限于按名称验证线程。幸运的是,Schedulers.io()使用的线程以我们可以匹配的一致前缀命名。以下是具有唯一前缀供参考的(完整?)调度程序列表:

  • Schedulers.io() - RxCachedThreadScheduler
  • Schedulers.newThread() - RxNewThreadScheduler
  • Schedulers.computation() - RxComputationThreadPool

IO线程上验证Observable 订阅

// Calling Thread.currentThread() inside Observer.OnSubscribe will return the
// thread the Observable is running on (Schedulers.io() in our case)
Observable<String> obs = Observable.create((Subscriber<? super String> s) -> {
    s.onNext(Thread.currentThread().getName());
    s.onCompleted();
})

// Schedule the Observable
Usecase usecase = new Usecase(obs, Schedulers.immediate());
Observable usecaseObservable = usecase.execute();

// Verify the Observable emitted the name of the IO thread
String subscribingThread = usecaseObservable.toBlocking().first();
assertThat(subscribingThread).startsWith("RxCachedThreadScheduler");

要在计算线程上验证Observable 观察,您可以使用TestSubscriber#getLastSeenThread访问用于观察的最后一个线程。

TestSubscriber<Object> subscriber = TestSubscriber.create();
UseCase usecase = new UseCase(Observable.empty(), Schedulers.computation())
usecase.execute().subscribe(subscriber);

// The observable runs asynchronously, so wait for it to complete
subscriber.awaitTerminalEvent();
subscriber.assertNoErrors();

// Verify the observable was observed on the computation thread
String observingThread = subscriber.getLastSeenThread().getName();
assertThat(observingThread).startsWith("RxComputationThreadPool");

虽然我使用AssertJ来表达流畅的startsWith断言,但不需要第三方库或模拟。

答案 1 :(得分:2)

Observable上应用运算符会返回一个新的Observable,因此任何后续运算符应用程序都将在另一个对象上发生。您必须遵循Observable中的组合图来发现应用了哪些运算符以及使用了哪些参数。

RxJava不支持此功能,您必须依赖内部细节和反射。

通常情况下,您不能假设事件发生的位置,但您可以申请observeOn以确保他们到达您选择的主题。