Coroutine launch not waiting with StandardTestDispatcher

175 views Asked by At

I’ve a ViewModel that has a viewModelScope.launch{} on the init{}. I’m trying to run a test where I set Dispatchers.setMain(StandardTestDispatcher()) but the launch{} is running before I call advanceUntilIdle(). Why is that? Shouldn't it wait?

class TestViewModel : ViewModel() {

    val state = MutableStateFlow("A")

    init {
        viewModelScope.launch {
            state.update { "B" }
        }
    }
}
class TestViewModelTest {

    private lateinit var viewModel: TestViewModel

    @Before
    fun setup() {
        Dispatchers.setMain(StandardTestDispatcher())
        viewModel = TestViewModel()
    }

    @Test
    fun test() = runTest {
        assert(viewModel.state.value == "A") // Fails, value is "B"
        advanceUntilIdle()
        assert(viewModel.state.value == "B")
    }

}
1

There are 1 answers

2
Tgo1014 On BEST ANSWER

As explained in the issue opened on coroutine's GitHub, runTest automatically runs all enqueued tasks. With this in mind, changing the test to this fix it:

@Test
fun test() {
    assert(viewModel.state.value == "A")
    runTest {
        advanceUntilIdle()
        assert(viewModel.state.value == "B")
    }
}