Существует много разговоров об использовании различных Schedulers
в тесте и множество решений для достижения этой цели:
Я понимаю, почему я должен заменить AndroidSchedulers.mainThread()
на другой планировщик, поэтому я не вижу этой проблемы .
Но я не до конца понимаю причины замены планировщиков .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);
});
}
}
На самом деле я бы никогда не получил NPE на currentNumber
, поскольку наблюдаемый конструктор завершился бы задолго до того, как был вызван someMethod
, но в тесте:
@Test
public void someMethodTest() {
MyClass myClass = new MyClass();
myClass.someMethod();
}
Я бы получил NPE на currentNumber
. Технически это состояние гонки, но я бы видел это только в тестах. В прошлом я исправил это с помощью:
@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
в конструкторе, где я ожидаю увидеть значение почти сразу.