Search code examples
androidunit-testingjunitrx-java2

RxJava 2. Verify TestObserver's invocation order


I have two observables in my API (view model can show the main idea, it's only example):

interface ViewModel {
    val height: Observable<Int>
    val color: Observable<Int>

    fun refresh()
}

How can I verify invocation order of TestObserver in unit test:

@Test
fun `When vm refresh, then color should be applied and then height`() {
    val heightObserver = vm.height.test()
    val colorObserver = vm.color.test()

    vm.refresh()

    // how to verify colorObserver value should be delivered first?
}

In common case we shouldn't rely on order, but question however: are we have a way to verify order and how?


Solution

  • I suggest using the merge operator. For example, these observables implements as ReplaySubject(not necessarily, there may be any other):

    class ViewModelImpl : ViewModel {
        private val colorSubject = ReplaySubject.create<Int>()
        private val heightSubject = ReplaySubject.create<Int>()
    
        override val height: Observable<Int> = heightSubject
        override val color: Observable<Int> = colorSubject
    
        override fun refresh() {
            colorSubject.onNext(1)
            colorSubject.onNext(2)
            colorSubject.onNext(3)
    
            heightSubject.onNext(4)
            heightSubject.onNext(5)
            heightSubject.onNext(6)
        }
    }
    

    For such an implementation, this test will succeed:

    @Test
    fun refresh() {
        val vm: ViewModel = ViewModelImpl()
        vm.refresh()
        Observable.merge(vm.color, vm.height)
                .test()
                .assertValues(1, 2, 3, 4, 5, 6)
    }
    

    And this a test is performed with an error:

    @Test
    fun name() {
        val vm: ViewModel = ViewModelImpl()
        vm.refresh()
        Observable.merge(vm.color, vm.height)
                .test()
                .assertValues(4, 5, 6, 1, 2, 3)
    }