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")
}
}
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")
}
}