-
Notifications
You must be signed in to change notification settings - Fork 1.9k
Open
Description
Describe the bug
The kotlinx-coroutines-test test framework may fail to run some code to completion if a test dispatcher was passed to the system under test.
The recommended approach is to pass a CoroutineScope to the system under test, which allows the test to know that some operations in the system under test may still be running. When only a dispatcher is passed, a new task may arrive there by the time runTest is no longer processing the tasks in the test scheduler.
Provide a Reproducer
import kotlinx.coroutines.test.*
import kotlinx.coroutines.*
import kotlin.time.Duration.Companion.milliseconds
import kotlin.concurrent.thread
suspend fun waitForSomethingAsynchronousToHappen() {
val latch = CompletableDeferred<Unit>()
thread {
Thread.sleep(100)
latch.complete(Unit)
println("Latch lowered")
}
latch.await()
}
fun runSomeTestThing(dispatcher: CoroutineDispatcher) {
GlobalScope.launch(dispatcher) {
try {
println("Starting a new task")
waitForSomethingAsynchronousToHappen()
} finally {
println("Cleaning up")
}
}
}
fun main() {
val dispatcher = StandardTestDispatcher()
TestScope(dispatcher).runTest {
runSomeTestThing(dispatcher)
}
println("Test finished")
Thread.sleep(300)
println("Tired of waiting")
}prints
Starting a new task
Test finished
Latch lowered
Tired of waiting
The cleanup never runs.