RxJava 2:BehaviorSubject和Observable.combineLatest问题

时间:2018-01-07 18:35:35

标签: java android unit-testing rx-java rx-java2

我在组合BehaviorSubjectObservable.combineLatest方面遇到了一些问题。我能够在(较小的)测试中重现它。这是一个目前失败的测试:

import org.junit.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import io.reactivex.Observable;
import io.reactivex.observers.TestObserver;
import io.reactivex.subjects.BehaviorSubject;
import io.reactivex.subjects.Subject;

import static java.util.Collections.singletonList;

public class MyTest {

    @Test
    public void test() {
        Subject<Integer> intSource = BehaviorSubject.createDefault(1);

        Subject<List<Observable<Integer>>> mainSubject = 
            BehaviorSubject.createDefault(singletonList(intSource));

        TestObserver<List<Integer>> testObserver = 
            mainSubject.flatMap(observables ->
                Observable.combineLatest(observables, this::castObjectsToInts)
            )
            .test();

        List<Observable<Integer>> newValue = new ArrayList<>();
        newValue.add(intSource); // same value as before
        newValue.add(Observable.just(2)); // add another value to this list.

        mainSubject.onNext(newValue);

        // intSource was already '1', but this is just to 'update' it.
        intSource.onNext(1); // COMMENT OUT THIS LINE

        testObserver.assertValueAt(0, singletonList(1));
        testObserver.assertValueAt(1, Arrays.asList(1, 2));
        testObserver.assertValueAt(2, Arrays.asList(1, 2)); // COMMENT OUT THIS LINE
        testObserver.assertValueCount(3); // REPLACE 3 WITH 2
    }

    private List<Integer> castObjectsToInts(Object[] objects) {
        List<Integer> ints = new ArrayList<>(objects.length);
        for (Object object : objects) {
            ints.add((Integer) object);
        }
        return ints;
    }
}

(如果你用“评论此线条”注释掉这两行,并用3替换最后一个2,则测试成功。)

为什么这个测试失败了?我没有看到代码有任何问题。

1 个答案:

答案 0 :(得分:1)

它失败是因为您忘记了mainSubject.flatMap仍然有第一个intSource处于活动状态,因此intSource.onNext(1)将首先触发combineLatest序列。然后testObserver.assertValueAt(2)将成为List中的单个值。 assertValueAt(3)将包含1, 2,整个序列包含4个项目。