In a `TestScope`, how can I manually control the p...
# coroutines
l
In a
TestScope
, how can I manually control the passing of virtual time inside a suspending function?
Copy code
suspend fun doSomethingDelayed() {
    delay(10.seconds)
    println("Delayed action completed")
}
The test (in Kotest):
Copy code
"test do something delayed" {
            doSomethingDelayed()
            testCoroutineScheduler.advanceTimeBy(5.seconds)
            testCoroutineScheduler.runCurrent()
            println("5 seconds passed")
            testCoroutineScheduler.advanceTimeBy(5.seconds)
            testCoroutineScheduler.runCurrent()
            println("Test completed")
        }
It prints
Copy code
Delayed action completed
5 seconds passed
Test completed
a
Use
launch { doSomethingDelayed() }
.
l
And then
advanceTimeBy()
inside or outside of
launch()
?
d
Relevant: https://github.com/Kotlin/kotlinx.coroutines/issues/3919
advanceTimeBy()
can be replaced by a
delay
in most cases.
a
Outside. The test scheduler handles the execution (delay) of the launched coroutine and you controls the scheduler from outside.
l
Thank you both!
The test actually works as expected like this:
Copy code
"test do something delayed" {
            launch {
                doSomethingDelayed()
            }
            delay(5.seconds)
            println("5 seconds passed")

            delay(5.seconds)
            println("Test completed")
        }
@Dmitry Khalanskiy [JB] why does
advanceTimeBy()
not work as expected here?
d
I'd expect it, too, to work here. Does it not? What happens instead? If you send me a full file, I'll take a look and explain what's going on.
l
I will create a reproducer project
d
Oh, wait, I think I got it. Are you asking why this doesn't work?
Copy code
"test do something delayed" {
            launch {
                doSomethingDelayed()
            }
            advanceUntilIdle(5.seconds)
            println("5 seconds passed")

            advanceUntilIdle(5.seconds)
            println("Test completed")
        }
If yes, it's because
advanceTimeBy(duration)
stops right before executing the tasks scheduled to execute
duration
later. To execute those tasks,
advanceTimeBy
should be followed by
runCurrent
. This gives much more flexible control in the technical scenarios where manually controlling virtual time is actually necessary.
l
So in my reproducer project I couldn't reproduce this problem with
advanceTimeBy()
anymore. It must lie somehow in my Kotest configuration in my main project.