Vlad
04/18/2022, 1:04 PMcoroutines-test:1.5
to 1.6.1 and can’t wrap my head around some of the new behaviours.
In 1.6 we seemingly have lost the ability to control the dispatch of individual dispatchers used internally by the classes under test, since all of the test dispatchers have to use a shared TestCoroutineScheduler
that now is the owner of the shared virtual time.
More details in the thread.Vlad
04/18/2022, 1:06 PMclass AsyncWorkRunner(
private val asyncWorkScope: CoroutineScope,
private val backgroundDispatcher: CoroutineDispatcher
) {
...
fun scheduleWork() {
asyncWorkScope.launch(backgroundDispatcher) {
// someExpensiveWorkThatMightTakeSomeTime()
workResult.tryEmit(Complete)
}
}
suspend fun waitForWorkToCompleteWithTimeout() {
if (workResult.value != Complete) {
withTimeout(100) { workResult.first { it == Complete } }
}
}
}
In 1.5, I could provide 2 independent TestCoroutineDispatcher
s: one for runBlockingTest
and another for the backgroundDispatcher
. This would allow to pause the execution of backgroundDispatcher
and advance the test dispatcher only, like so:
runBlockingTest(testBlockDispatcher) {
backgroundWorkDispatcher.pauseDispatcher()
workRunner.scheduleWork()
val timeBeforeWait = testBlockDispatcher.currentTime
workRunner.waitForWorkToCompleteWithTimeout() //testBlockDispatcher auto-advanced due to the use of withTimeout
assertThat(testBlockDispatcher.currentTime - timeBeforeWait).isEqualTo(100)
}
This is no longer possible with coroutines-test:1.6
using any of the test dispatchers since TestCoroutineScheduler
must be shared between the test block dispatcher and the backgroundDispatcher
otherwise a Detected use of different schedulers
error is thrown. If the same scheduler is used, runCurrent
would advance both of them at the same time which prevents me from testing the timeout behaviour.
I was sort of able to mimic the old behaviour by writing my own CoroutineDispatcher
that never dispatches anything and by swapping it around when needed. But this seems… complicated and too limiting. It feels like I am missing something fundamental. Is there a way of precise control of when the internal dispatchers run with coroutines 1.6?Alex Vanyo
04/18/2022, 5:50 PMsomeExpensiveWorkThatMightTakeSomeTime()
, then in one test you could have it delay by 50
, and in another you could have it delay by 150
, and in the latter case you should expect to see the timeout hit.Vlad
04/18/2022, 6:38 PM