Thomas Vos
Thomas Vos

Reputation: 12571

RxJava 2: BehaviorSubject and Observable.combineLatest issues

I'm having some issues with combining both a BehaviorSubject and Observable.combineLatest. I was able to reproduce it in a (smaller) test. Here is a test which is currently failing:

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;
    }
}

(If you comment out both lines with "COMMENT OUT THIS LINE", and replace the last 3 with a 2, the test succeeds.)

Why is this test failing? I don't see anything wrong with the code.

Upvotes: 1

Views: 2513

Answers (1)

akarnokd
akarnokd

Reputation: 70007

It fails because you forgot that the mainSubject.flatMap still has the first intSource active, thus the intSource.onNext(1) will first trigger that combineLatest sequence. The testObserver.assertValueAt(2) then will be that single value in a List. assertValueAt(3) will contain the 1, 2 instead and the whole sequence has 4 items.

Upvotes: 2

Related Questions