My Android app is using Jetpack Compose. Inside one of my @Composable functions, I get a coroutine scope:
@Composable
fun MyComposable() {
val scope = rememberCoroutineScope()
// ...
Then, I use it in one of my buttons' onClick to run a suspend function:
Button(onClick = {
scope.launch {
doThings()
}
}) {
// ...
}
}
suspend fun doThings() {
// ...
}
I'd like to do an Espresso test of the click's results. However, immediately after
onNode(/* ... */).performClick()
doThings() isn't done yet. I'd like to wait until doThings() finishes, without using Thread.sleep(), something like:
waitUntil { theThingsAreDone() }
Is there any way I can do this without putting the test code in my production code?
If I could replace scope in my test, then I could use one that incremented and decremented a CountingIdlingResource, thus making Espresso wait for it automatically. Passing scope as a parameter to MyComposable might give me that control, but then I'd lose the behavior of rememberCoroutineScope(). Can I modify scope in my test, while having it still follow the behavior of rememberCoroutineScope()?
You can use
waitUntilto wait a specified maximum amount of time until a condition is true. So you just need some sort of condition to check whether the async operation was finished.If you have asynchronous functions in your
ViewModelthat you want to test, the only way I found to achieve it was as follows:1.) Move your dispatcher definition into the function signature:
2.) Call the function as
runBlockingto make sure that it was executed after you reach the next statement: