Kotlin协程使用runBlocking进行单元测试不等待执行

时间:2019-01-06 12:34:10

标签: android kotlin kotlinx.coroutines

有什么方法可以等待示波器中正在运行的挂起函数,例如runBlocking对正在运行的挂起函数做什么?

例如,

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是一个挂起函数,并且我在单元测试中使用runBlocking运行了它,那么一切都会正常进行。

我尝试过与其他自定义调度程序(如下面的调度程序)配合使用,这些调度程序可以阻塞地执行任务,但是没有运气

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

1 个答案:

答案 0 :(得分:1)

好的,所以我知道了正在发生什么。不等待启动,因为从不使用它的返回值。

在上面的示例中,testFunction应该返回启动的返回值,该值是可以等待/加入的Deffered对象。因此,要真正等待其完成,必须对代码进行如下更改:

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秒(使用无限制调度程序)。