Does anyone know how to unit test code which uses ...
# coroutines
m
Does anyone know how to unit test code which uses
Flow.debounce
? The unit test doesn't wait until debounce is completed. It should actually advance the delay since I'm using
runBlockingTest
as per the documentation, but that doesn't happen. Here is an example that reproduces my case.
Copy code
class DebounceTest(scope: CoroutineScope) {
    private val stateFlow = MutableStateFlow("")
    val resultFlow = MutableStateFlow("")

    init {
        stateFlow.debounce(500)
            .onEach {
                resultFlow.value = it
            }
            .launchIn(scope)
    }

    fun search(text: String){
        stateFlow.value = text
    }
}

@Test
    fun debounceTest() = runBlockingTest {
        val sut = DebounceTest(this)
        sut.search("test")
        assertThat(sut.resultFlow.value).isEqualTo("test")
    }
The test here fails saying the actual value of
resultFlow.value
is empty string instead of
test
m
If you want to manipulate time in your test you have to do that manually by calling
advanceTimeBy(500)
after
sut.search("test")
runBlockingTest
allows you to control the time but doesn’t do anything automatically during the test execution.
m
Thanks,
advancedtimeBy
works, but I'm blocked by this issue https://github.com/Kotlin/kotlinx.coroutines/issues/1531 I'm getting
Test finished with active jobs
error since the job inside the
DebounceTest
init block is not canceled. And I can't cancel it manually since my actual code is Android
ViewModel
and it uses
viewModelScope
inside it.
😞 1
👍 1
n
I'm not sure the linked issue is related since
viewModelScope
creates its own scope (unless you create the
TestCoroutineScope
with
viewModelScope
). There's also a workaround in the issue. What's stopping you from just calling
cancel
on
viewModelScope
? If you are still stuck, maybe you could post a trivial example to show how you are setting up your unit test?
m
@Nick Allen I fixes the issue. The issue was, I was using two different `TestCoroutineDisoatcher`'s and that caused this issue. I used the same diaptcher I pass to Viewmodel to start
runBlockingTest
and it worked fine after that. https://stackoverflow.com/a/67897542
441 Views