Kotlin coroutines unit testing with runBlocking 不等待执行

Kotlin coroutines unit testing with runBlocking does not wait for execution

有什么方法可以等待范围内 运行ning 的挂起函数,就像 运行Blocking 为其 运行ning 挂起函数所做的那样?

例如,

class CoroutineTestCase : CoroutineScope {
    val job = Job()
    var value = 1
    override val coroutineContext: CoroutineContext
        get() = job + Dispatchers.Unconfined


    fun testFunction() {
         async {
             delay(2000)
             value = 2
        }
    }
}

@Test
fun testCoroutine() = runBlocking {
    val coroutineTestCase = CoroutineTestCase()
    coroutineTestCase.testFunction()
    assertEquals(2, coroutineTestCase.value)
}

以上测试失败,值为 1 且未更改(因为未等待 launch 完成)。如果 testFunction 是一个挂起函数并且我 运行 它在我的单元测试中使用 运行 阻塞,那么一切都会成功。

我试过使用其他可以阻塞 运行 他们的任务的自定义调度程序(如下所示),但运气不好

class TestUiContext : CoroutineDispatcher() {
     override fun dispatch(context: CoroutineContext, block: Runnable) {
         block.run()
    }
}

好的,我知道发生了什么。未等待启动,因为它的 returned 值从未使用过。

在上面的示例中,testFunction 应该 return launch 的 returned 值,它是一个 Deffered 对象,可以是 awaited/joined。所以要真正等待它完成,代码必须更改如下:

class CoroutineTestCase : CoroutineScope {
    val job = Job()
    var value = 1
    override val coroutineContext: CoroutineContext
        get() = job + Dispatchers.Unconfined


    fun testFunction(): Deferred<Unit> {
         return async {
                 delay(20000)
                 value = 2
        }
    }
}

@Test
fun testCoroutine() = runBlocking {
    val coroutineTestCase = CoroutineTestCase()
    coroutineTestCase.testFunction().await()
    assertEquals(2, coroutineTestCase.value)
}

目前唯一的问题是,在这种情况下,它实际上延迟了 20 秒(使用 unconfined dispatcher)。