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)。
有什么方法可以等待范围内 运行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)。