Apologies for what is probably a very amateur question.
I'm getting to grips with flows and having issues with testing where MutableSharedFlow
is concerned.
The following is the simplest example I can construct that recreates the problem:
@ExperimentalCoroutinesApi
@ExperimentalTime
class MyExampleTest {
val testDispatcher: TestCoroutineDispatcher = TestCoroutineDispatcher()
@Test
fun test() = testDispatcher.runBlockingTest {
val sharedFlow = MutableSharedFlow<String>()
sharedFlow.take(2).collect {
println(it)
}
sharedFlow.tryEmit("Hello")
sharedFlow.tryEmit("World")
}
}
This results int he following error:
java.lang.IllegalStateException: This job has not completed yet
at kotlinx.coroutines.JobSupport.getCompletionExceptionOrNull(JobSupport.kt:1187)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:53)
at kotlinx.coroutines.test.TestBuildersKt.runBlockingTest(TestBuilders.kt:80)
at com.example.MyExampleTest.test(MyExampleTest.kt:22)
From my limited understanding I think it's something to do with the fact that SharedFlow
never completes. But I thought having the take(2)
would mitigate this. Any suggestions would be appreciated!
From my limited understanding I think it's something to do with the fact that SharedFlow never completes.
You're right, this is more or less the problem. Flow is based on Coroutines and the coroutine has not completed.
The best way to unit test Flows in my opinion is Turbine:
https://github.com/cashapp/turbine
// Cold Flow
flowOf("one", "two").test {
assertEquals("one", expectItem())
assertEquals("two", expectItem())
expectComplete()
}
// Hot Flow
MutableStateFlow("test").test {
assertThat(expectItem()).isEqualTo("test")
cancelAndConsumeRemainingEvents()
}
There is also an open issue about this exact "problem":
https://github.com/Kotlin/kotlinx.coroutines/issues/1204
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With