我有以下课程(简化):
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);
}
}
我正在为它编写单元测试。如何测试使用正确的值调用subscribeOn
和observeOn
?
我尝试以下方法:
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
以上失败(我认为),因为subscribeOn
和observeOn
是final
方法。那么可能还有其他方法可以确保observable使用正确的调度程序吗?
答案 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
以确保他们到达您选择的主题。