https://kotlinlang.org logo
#coroutines
Title
# coroutines
j

Jan Skrasek

10/08/2020, 8:15 AM
Let's have a flow collection. Something like
Copy code
interface Foo {
    suspend fun test(i: Int)
  }

  @Test
  fun myTest() = testCoroutineDispatcher.runBlockingTest {
    val mutableState: MutableStateFlow<Int> = MutableStateFlow(1)

    val foo = mockk<Foo>()

    val job = launch {
      mutableState
        .filter { it != 1 }
        .collect {
          delay(100)
          foo.test(it)
        }
    }

    mutableState.value = 2

    // how to wait here to be able to verify?

    coVerify {
      foo.test(2)
    }
  }
How to wait for the flow collection? Some part of the flow runs immediately and ultimately the execution is switched back to the test and assertion fails since the collection haven't run yet.
b

bezrukov

10/08/2020, 8:26 AM
Copy code
val synchronizeJob = launch {
      myClass.startSynchronize()
}

// your emits

synchronizeJob.join()
j

Jan Skrasek

10/08/2020, 9:27 AM
I've updated the example. Calling join on job will actually wait for flow completion, but it is not complete. Calling cancel will immediately cancel and first collection won't run.
b

bezrukov

10/08/2020, 10:14 AM
because StateFlow never completes. So that collect job will never complete either. You can try to invoke
Copy code
testCoroutineDispatcher.advanceUntilIdle()
after value update, and then cancel job.
j

Jan Skrasek

10/08/2020, 10:28 AM
Oh nice, that works! thanks!
Oh, half of the issue was that I was missing some stubing and the thrown exception wasn't printed / caught anywere, just let the main test function continue :X
3 Views