@ExperimentalCoroutinesApi
class MyTest {
class MyViewModel {
private val _state = MutableStateFlow(false)
val state = _state.asStateFlow()
fun doSomething(runYield: Boolean) {
val viewModelScope = CoroutineScope(SupervisorJob() + Dispatchers.Main.immediate) // btw. this is how Android provides a `viewModelScope`
viewModelScope.launch {
_state.value = true
// some workload here
if (runYield)
yield()
_state.value = false
}
}
}
@Before
fun setUp() {
Dispatchers.setMain(UnconfinedTestDispatcher())
}
@After
fun tearDown() {
Dispatchers.resetMain()
}
@Test
fun `Failing test`() = runTestCase(runYield = false)
@Test
fun `Passing test`() = runTestCase(runYield = true)
private fun runTestCase(runYield: Boolean) = runTest {
val viewModel = MyViewModel()
// Collect emissions to `state` in this mutable list
val testResults = mutableListOf<Boolean>()
// backgroundScope makes sure the job is shut down after the test
backgroundScope.launch(UnconfinedTestDispatcher(testScheduler)) {
viewModel.state.toList(testResults)
}
viewModel.doSomething(runYield)
assertEquals(listOf(false, true, false), testResults)
}
}
使用 a MutableSharedFlow 代替 the MutableStateFlow 也可以缓解该问题。