关于在测试中使用不同的Schedulers
的讨论很多,并且有很多解决方案来实现这一目标:
我了解为什么我应该用另一个调度程序替换AndroidSchedulers.mainThread()
,所以看不到this problem。
但是我不完全理解用.io()
替换computation()
和trampoline()
调度程序的原因吗?
大概这将同步所有Rx流。假设我有两个流:一个在构造函数中,一个在someMethod
***中:
import android.util.Log;
import io.reactivex.Observable;
import io.reactivex.schedulers.Schedulers;
public class MyClass {
private Integer currentNumber;
public MyClass() {
Observable.just(1, 2, 3)
.subscribeOn(Schedulers.io())
.subscribe(integer -> currentNumber = integer);
}
public void someMethod() {
Observable.just("A", "B", "C")
.subscribeOn(Schedulers.io())
.subscribe(s -> {
// add current string to current number
Log.d("TAG", s + currentNumber);
});
}
}
实际上,我永远不会在currentNumber
上获得NPE,因为可观察到的构造函数会在调用someMethod
之前很久就完成。但是在测试中:
@Test
public void someMethodTest() {
MyClass myClass = new MyClass();
myClass.someMethod();
}
我将在currentNumber
上获得NPE。从技术上讲,这是一个竞赛条件,但我只能在测试中看到它。过去,我已通过以下方式解决此问题:
@Test
public void someMethodTest() throws Exception {
MyClass myClass = new MyClass();
Thread.sleep(100); // sleep to allow constructor's observable to complete.
myClass.someMethod();
}
那么在测试中替换非主线程调度程序是一个好主意吗?理想情况下,我希望测试尽可能与真实代码相似。我是否应该通过重构MyClass
来解决竞争条件?
*** 这是一个简单的示例,但是当我在构造函数中订阅BehaviorSubject
或ReplaySubject
时,我看到了很多,我希望观察到几乎立即值。