Лучшие практики при замене не основных планировщиков потоков в тестах? - PullRequest
0 голосов
/ 08 сентября 2018

Существует много разговоров об использовании различных 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 в конструкторе, где я ожидаю увидеть значение почти сразу.

...