【发布时间】:2020-04-24 11:08:45
【问题描述】:
所以也许有一个教程来解决这个问题,但我读过的那些都没有为我解决这个问题。我的结构如下,并且正在尝试进行单元测试,但是当我去测试时,我总是无法说明 repo 方法 doSomthing() 从未被调用过。我最好的猜测是因为我在不同的上下文中启动了一个新的协程。那我该如何测试呢?
存储库
interface Repository {
suspend fun doSomething(): String
}
查看模型
class ViewModel(val repo: Repository) {
val liveData = MutableLiveData<String>()
fun doSomething {
//Do something here
viewModelScope.launch(Dispatchers.IO) {
val data = repo.doSomething()
withContext(Dispatchers.Main) {
liveData.value = data
}
}
}
}
查看模型测试
class ViewModelTest {
lateinit var viewModel: ViewModel
lateinit var repo: Repository
@Before
fun setup() {
Dispatchers.setMain(TestCoroutineDispatcher())
repo = mock<Repository>()
viewModel = ViewModel(repo)
}
@Test
fun doSomething() = runBlockingTest {
viewModel.doSomething()
viewModel.liveData.test().awaitValue().assertValue {
// assert something
}
verify(repo).doSomthing()
}
}
【问题讨论】:
-
viewModelScope是如何设置的?如果你把它暴露给测试,你可以写viewModelScope.coroutineContext[Job]!!.children.forEach { it.join() }。但是,这仍然是不稳定的,因为测试不知道您将启动多少子作业以及何时启动它们。您可能会得到一个空的children列表。我处理类似问题的方法是使用assertTrueEventually原语,该原语不断重试断言,直到满足或超时为止。 -
另外,我对您的代码有一个一般性评论:在 Main 调度程序中启动协程并让
suspend fun doSomething()根据需要在内部使用 IO 调度程序会更好。这不应该是调用者关心的问题。 -
viewModelSCope 是 Android 提供的一个扩展函数,它使用 Dispatchers.Main ... @MarkoTopolnik
标签: android unit-testing kotlin kotlin-coroutines