I'm trying to test a Flow that uses shareIn
with Turbine, but I'm a bit lost why my tests are failing and how I can fix it.
class MyTest {
private val scope = CoroutineScope(Dispatchers.Default)
private val mutableSharedFlow = MutableSharedFlow<Int>()
@Test
fun succeeds() = runBlocking {
val sharedFlow = mutableSharedFlow
sharedFlow.test {
expectNoEvents()
mutableSharedFlow.emit(3)
expect(expectItem()).toBe(3)
}
}
@Test
fun fails() = runBlocking {
val sharedFlow = mutableSharedFlow
.shareIn(scope, started = SharingStarted.WhileSubscribed())
sharedFlow.test {
expectNoEvents()
mutableSharedFlow.emit(3)
expect(expectItem()).toBe(3)
}
}
}
In these tests, the first succeeds()
test runs fine, but as soon as I include shareIn
in the fails()
test, the test fails with a timeout:
Timed out waiting for 1000 ms
kotlinx.coroutines.TimeoutCancellationException: Timed out waiting for 1000 ms
(Coroutine boundary)
at app.cash.turbine.ChannelBasedFlowTurbine$expectEvent$2.invokeSuspend(FlowTurbine.kt:238)
at app.cash.turbine.ChannelBasedFlowTurbine$withTimeout$2.invokeSuspend(FlowTurbine.kt:206)
at app.cash.turbine.ChannelBasedFlowTurbine.expectItem(FlowTurbine.kt:243)
What should I do to test flows that use shareIn
?
I do not know why you've decided to use a scope with Dispatchers.Default
as here:
...
private val scope = CoroutineScope(Dispatchers.Default)
...
For tests, just use Dispatchers.Unconfined
instead because it executes coroutines immediately on the current thread and that's exactly what you need there.
...
private val scope = CoroutineScope(Dispatchers.Unconfined)
...
So, after applying the change above, both of your tests passed successfully.
You can find my sample project for this question here.