如何测试该块是否在协同例程调度程序上运行,如果它通过启动(调度程序){...}调用



我们最近开始在Android应用程序上使用协程。一切都很顺利,直到有人写了一些大致相当于以下函数的东西:

fun example(dispatcher: CoroutineDispatcher, block: () -> Unit) {
    launch(dispatcher) {
        block()
    }
}

我们想编写一个测试来验证block是否使用 dispatcher 执行。

我们已经尝试了以下方法,但这不起作用,因为我们得到了一个 NullPointerException,因为dispatcher.parentContext没有被模拟。我不愿意嘲笑它,因为我们不在乎它在什么上下文中执行,只关心它是执行的:

@Test
fun `test that doesn't work`() {
    val dispatcher: CoroutineDispatcher = mock()
    val block: () -> Unit = mock()
    // fails here, specifically on the call to `launch` in example()
    example(dispatcher, block)
    val captor = argumentCaptor<Runnable>()
    verify(dispatcher).dispatch(any(), captor.capture())
    verify(block, never()).invoke()
    captor.firstArgument.run()
    verify(block).invoke()
}

我们已经把它作为一种选择,但它仍然感觉不对:

@Test
fun `test that works but doesn't feel right`() {
    val executor: ExecutorService = mock()
    val block: () -> Unit = mock()
    example(executor.asCoroutineDispatcher(), block)
    val captor = argumentCaptor<Runnable>()
    verify(executor).execute(captor.capture())
    verify(block, never()).invoke()
    captor.firstArgument.run()
    verify(block).invoke()
}

谁能想出更好的办法?

编辑:

值得注意的依赖关系如下:

com.nhaarman:mockito-kotlin:1.5.0
org.jetbrains.kotlinx:kotlinx-coroutines-core:0.22.5
junit:junit:4.12
org.jetbrains.kotlin:kotlin-stdlib:1.2.30

由于launch返回一个Job,您需要等待其完成才能验证已完成的任何操作。

您可以通过两种方式执行此操作:

由于您正在launch协程,因此实际的单元测试可能会在启动执行完成之前完成。您需要等待其执行,以确保测试不会提前完成。您可以通过多种方式执行此操作。

  1. 更改函数签名以从启动返回作业(例如 fun example(dispatcher: CoroutineDispatcher, block: () -> Unit) = launch(dispatcher) { ... .这样,您可以在example函数上调用.join()以等待其完成。

    1. 保留一个内部var exampleJob:Job? = null,并使用启动的执行进行设置,例如 exampleJob = launch { ...} .这样,在测试中,您可以使用exampleJob.join()等待其完成,然后再进行验证。

奖金解决方案:

你也可以使用MockK来verifyWithTimeout你的单元测试。这样,单元测试将等待验证完成。

相关内容

  • 没有找到相关文章

最新更新