What's the proper way to test if a flow collector ...
# coroutines
b
What's the proper way to test if a flow collector received a value emitted by a sharedflow? using
runTest
doesn't seem to wait for a collector running in another scope to fully process the emitted value before returning. Keeping everything in the runTest scope and context just hangs the test because Flow.collect on a sharedflow never returns.
t
b
I found this article: https://jeff-padgett.medium.com/unit-testing-mutablesharedflow-12aec5b6e05 Which was a bit outdated because it used runBlockingTest. I tried it with:
Copy code
@Test
    fun `does this even work`() {
        val emitter = MutableSharedFlow<String>()
        var emitted: String? = null
        runTest {
            val job = launch {
                emitter.collect { emitted = it }
            }
            emitter.emit("new value")

            job.cancel()
        }
        assertEquals("new value", emitted)
    }
But this test failed. Upon further investigation, replacing
runTest
with
runTest(UnconfinedTestDispatcher())
(to get similar behavior as
runBlockingTest
) is what made it pass. Fingers crossed this remains consistent.
t
That test will fail most likely due to the job being canceled before the block inside of launch is called
you could test by adding a delay in between the emit and the cancel to verify
b
That's what was happening with
runTest
on its own, but the
UnconfinedTestDispatcher
"eagerly enters all launch calls," so it actually behaves as I'd like it to.
t
Copy code
launch(start = CoroutineStart.UNDISPATCHED)
could also work more how you’re expecting
b
True, though, my actual use case is a bit more complicated than the simplified example. The
launch
call is happing in production code, so I'm getting it to pass by providing the production code with a coroutine scope that will behave the way I need 🙂