我的 Android 应用程序正在使用 Jetpack Compose。在我的一个
@Composable
函数中,我得到了一个协程作用域:
@Composable
fun MyComposable() {
val scope = rememberCoroutineScope()
// ...
然后,我在其中一个按钮的
onClick
中使用它来运行挂起功能:
Button(onClick = {
scope.launch {
doThings()
}
}) {
// ...
}
}
suspend fun doThings() {
// ...
}
我想对点击结果进行 Espresso 测试。然而,紧接着
onNode(/* ... */).performClick()
doThings()
还没完成。我想等到 doThings()
完成,而不使用 Thread.sleep()
,例如:
waitUntil { theThingsAreDone() }
有什么方法可以在不将测试代码放入生产代码中的情况下做到这一点?
如果我可以在测试中替换
scope
,那么我可以使用一个递增和递减 CountingIdlingResource
的函数,从而使 Espresso 自动等待它。将 scope
作为参数传递给 MyComposable
可能会给我这种控制权,但随后我就会失去 rememberCoroutineScope()
的行为。我可以在测试中修改 scope
,同时让它仍然遵循 rememberCoroutineScope()
的行为吗?
waitUntil
等待指定的最长时间,直到条件成立。所以你只需要某种条件来检查异步操作是否完成。
testRule.waitUntil(1000) { myCondition }
如果您想要测试的
ViewModel
中有异步函数,我发现实现它的唯一方法如下:
1.) 将调度程序定义移至函数签名中:
fun asyncOperation(coroutineContext: CoroutineContext = Dispatchers.IO) {
viewModelScope.launch(coroutineContext) {
// async operation...
}
}
2.) 将函数调用为
runBlocking
,以确保它在到达下一条语句后被执行:
@Test
fun test_asyncOperation() {
//...
runBlocking { myViewModel.asyncOperation(coroutineContext) }
//...
// Here, you can be sure that asyncOperation completed
}