Skip to content

The test coroutine scheduler isn't closed when a test ends #4580

@dkhalanskyjb

Description

@dkhalanskyjb

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.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions