fra*_*yan 10 kotlin kotlin-coroutines kotlin-flow
我对 Kotlin 协程和流程以及它们的单元测试很陌生。我有一个非常简单的测试:
@Test
fun debounce(): Unit = runBlocking {
val state = MutableStateFlow("hello")
val debouncedState = state.debounce(500).stateIn(this, SharingStarted.Eagerly, "bla")
assertThat(debouncedState.value).isEqualTo("bla")
state.value = "good bye"
// not yet...
assertThat(debouncedState.value).isEqualTo("bla")
delay(600)
// now!
assertThat(debouncedState.value).isEqualTo("good bye")
// cannot close the state flows :(
cancel("DONE")
}
Run Code Online (Sandbox Code Playgroud)
它工作得很好(除了我无法阻止它,但这是一个不同的问题)。
接下来,我想测试我的ViewModel,其中包括完全相同的状态流。它基本上与上面的代码相同,但我认为它应该在相同的范围内运行,所以viewModel.someMutableStateFlow我尝试运行它viewModelScope:
@Test
fun debounce(): Unit = runBlocking {
val viewModel = MyViewModel()
// in view model the state and debouncedState are defined the same way as above
val state = viewModel.someMutableStateFlow
val debouncedState = state.debounce(500).stateIn(viewModel.viewModelScope, SharingStarted.Eagerly, "bla")
///////////////////////////////////////////////////
// Below is the same code as in previous example //
///////////////////////////////////////////////////
assertThat(debouncedState.value).isEqualTo("bla")
state.value = "good bye"
// not yet...
assertThat(debouncedState.value).isEqualTo("bla")
delay(600)
// now!
assertThat(debouncedState.value).isEqualTo("good bye")
// cannot close the state flows :(
cancel("DONE")
}
Run Code Online (Sandbox Code Playgroud)
但这一次debouncedState.value从未改变,它bla一直保持不变!这些状态不会发出任何东西。
这是否与我正在使用viewModelScope并且可能没有运行有关?
关于这里发生的事情的一些解释会很棒。
但是,某些 API(例如 viewModelScope)在底层使用硬编码的 Main 调度程序。
然后描述如何用 TestDispatcher 替换 Main 调度程序:
class HomeViewModelTest {
@Test
fun settingMainDispatcher() = runTest {
val testDispatcher = UnconfinedTestDispatcher(testScheduler)
Dispatchers.setMain(testDispatcher)
try {
val viewModel = HomeViewModel()
viewModel.loadMessage() // Uses testDispatcher, runs its coroutine eagerly
assertEquals("Greetings!", viewModel.message.value)
} finally {
Dispatchers.resetMain()
}
}
}
Run Code Online (Sandbox Code Playgroud)
引用这篇文章:
如果 Main 调度程序已替换为 TestDispatcher,则任何新创建的 TestDispatcher 将自动使用 Main 调度程序中的调度程序,包括由 runTest 创建的 StandardTestDispatcher(如果没有其他调度程序传递给它)。
该文档还描述了如何制定测试规则,因此您不必在每个测试中都执行此操作。
| 归档时间: |
|
| 查看次数: |
1286 次 |
| 最近记录: |