rxjava testScheduler race condition

Viewed 219

I stumbled upon a weird testScheduler behavior that I cannot wrap my head around. The code below is greatly simplified, but it origins in a real life issue.

Consider this test:

@Test
fun testSchedulerFun(){

    val testScheduler = TestScheduler()

    val stringsProcessor = PublishProcessor.create<String>()

    val completable = Completable.complete()

    completable
        .doOnComplete { stringsProcessor.onNext("onComplete") }
        .subscribeOn(testScheduler)
        .subscribe()

    val testSubscriber = stringsProcessor
        .subscribeOn(testScheduler) //this line of code messes the test
        .test()

    testScheduler.triggerActions()

    testSubscriber
        .assertValues("onComplete")

}

**When I subscribe the tested stringsProcessor on testScheduler, the test fails. When I remove that line it succeeds. **

The flow of events as I see it is:

  1. triggerActions
  2. completable and stringsProcessor are being subscribed and propagate their events downstream.
  3. And apparently the stringsProcessor.onNext("onComplete") is evaluated after the testSubscriber has finished.

I want to know why

1 Answers

The reason the test fails is because stringProcessor has no subscriber the time you call onNext on it. That subscriber only comes after because you added the "this line messes up" subscribeOn.

There is no race condition involved because everything runs on the same thread in a deterministic order:

  1. when the code executes completable ... subscribe() part, a task is queued with testScheduler that will perform the doOnComplete call.
  2. when the code executes the test part, another task is queued with testScheduler that will observe the processor.
  3. triggerActions executes task 1, which emits the value to no subscribers, then executes task 2 and now ready to observe the processor, but nothing comes.
Related