CXwudi
07/25/2024, 10:07 PMonIntent<LandingPageIntent.ToNextPage> {
launch {
... some other suspend fun call
publish(LandingPageToNextPageLabel)
log.d { "Label sent" }
}
Now I have two test cases in kotlintest. One has deadlock, another one doesn't. Here is the one with the deadlock:
@Test
fun normalFlowStucked() = runTest {
// the labels Flow way will be stuck if running in single-threaded env like JS or single-threaded Dispatcher
// However, from debugging, the label is actually dispatched, but for some reason, we can't receive it
val job = launch {
landingPageStore.labels.stateIn(CoroutineScope(coroutineContext)).collect {
log.d { "Received $it" }
assertEquals(LandingPageToNextPageLabel, it)
}
}
landingPageStore.accept(LandingPageIntent.TextChanged("a change"))
assertEquals("a change", landingPageStore.state.url)
landingPageStore.accept(LandingPageIntent.ToNextPage)
job.join()
}
The test case can still print "Label sent"
, but not "Received LandingPageToNextPageLabel"
. This only happens if running in jsTest
or in Android platform without specifying the Dispatchers.Default
. Now here is another test case that uses Channel
instead of `Flow`:
@Test
fun testNormalFlow1() = runTest {
// Can't make Store.labels Flow way working in single-threaded env like JS or single-threaded Dispatcher
val channel = Channel<LandingPageToNextPageLabel>()
val scope = CoroutineScope(coroutineContext)
landingPageStore.labels(observer {
scope.launch {
channel.send(it)
log.d { "Received $it" }
}
})
landingPageStore.accept(LandingPageIntent.TextChanged("a change"))
assertEquals("a change", landingPageStore.state.url)
landingPageStore.accept(LandingPageIntent.ToNextPage)
val label = channel.receive()
assertEquals(label, LandingPageToNextPageLabel)
channel.close()
}
This one runs successfully, no deadlock.
The actual codes are open sourced at [here](https://github.com/CXwudi/realworld-compose-http4k-example-app/blob/master/conduit[…]onduit/frontend/logic/component/landing/LandingPageStoreTest.kt) and [here](https://github.com/CXwudi/realworld-compose-http4k-example-app/blob/master/conduit[…]uit/frontend/logic/component/landing/LandingPageStoreFactory.kt) for references
So here are my questions:
1. Is the deadlock expected for the first test case?
2. Is the second test case a good way to test labels dispatching? If not, then what are some good way to test it?Arkadii Ivanov
07/25/2024, 11:34 PMlaunch {}
is asynchronous. By the time the launch block is called, the ToNextPage
intent has been already sent and processed, i.e. the label has been already emitted.
Please see the example of testing labels with coroutines: https://github.com/arkivanov/MVIKotlin/blob/018af7c8efc25f4d5d47058b202be756a36511[…]tlin/sample/coroutines/shared/details/store/DetailsStoreTest.kt
And the Flow.test
extension function: https://github.com/arkivanov/MVIKotlin/blob/018af7c8efc25f4d5d47058b202be756a36511[…]otlin/com/arkivanov/mvikotlin/sample/coroutines/shared/Utils.ktCXwudi
07/25/2024, 11:58 PM