Search code examples
androidunit-testingkotlinandroid-testingkotlin-coroutines

Unit testing a Kotlin coroutine with delay


I'm trying to unit test a Kotlin coroutine that uses delay(). For the unit test I don't care about the delay(), it's just slowing the test down. I'd like to run the test in some way that doesn't actually delay when delay() is called.

I tried running the coroutine using a custom context which delegates to CommonPool:

class TestUiContext : CoroutineDispatcher(), Delay {
    suspend override fun delay(time: Long, unit: TimeUnit) {
        // I'd like it to call this
    }

    override fun scheduleResumeAfterDelay(time: Long, unit: TimeUnit, continuation: CancellableContinuation<Unit>) {
        // but instead it calls this
    }

    override fun dispatch(context: CoroutineContext, block: Runnable) {
        CommonPool.dispatch(context, block)
    }
}

I was hoping I could just return from my context's delay() method, but instead it's calling my scheduleResumeAfterDelay() method, and I don't know how to delegate that to the default scheduler.


Solution

  • In kotlinx.coroutines v1.6.0 the kotlinx-coroutines-test module was updated. It allows tests to use the runTest() method and TestScope to test suspending code, automatically skipping delays.

    See the documentation for details on how to use the module.

    Previous Answer

    In kotlinx.coroutines v1.2.1 they added the kotlinx-coroutines-test module. It includes the runBlockingTest coroutine builder, as well as a TestCoroutineScope and TestCoroutineDispatcher. They allow auto-advancing time, as well as explicitly controlling time for testing coroutines with delay.