首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用mockk模拟协程的执行?

如何使用mockk模拟协程的执行?
EN

Stack Overflow用户
提问于 2018-11-09 17:34:11
回答 1查看 2K关注 0票数 0

我正在尝试使用mockk框架在我的一个单元测试中设置一个模拟,它执行一个挂起的函数,如下所示:

代码语言:javascript
复制
val executionCompletionSource = CompletableDeferred<Nothing>()
suspend fun task(): Unit = executionCompletionSource.await()
val mock = mockk<Executable> { coEvery { execute() } coAnswers { task() } }

然而,我发现如果我在启动的协程作用域中调用mock.execute(),测试会无限期地挂起。如果我在启动的作用域中直接调用task(),测试运行得很好。

尽管mockk documentation确实谈到了一些协程模拟,但我找不到任何文档或示例来说明如何执行协程来响应对模拟的挂起函数的调用。

下面是一个演示这一点的SSCCE:

代码语言:javascript
复制
package experiment

import io.mockk.coEvery
import io.mockk.mockk
import kotlinx.coroutines.CompletableDeferred
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking
import kotlin.system.measureTimeMillis

interface Executable {
    suspend fun execute()
}

fun main() {
    val executionCompletionSource = CompletableDeferred<Nothing>()
    suspend fun task(): Unit = executionCompletionSource.await()
    val mock = mockk<Executable> { coEvery { execute() } coAnswers { task() } }

    runBlocking {
        val execution = launch { mock.execute() } // This blocks the test indefinitely
        //val execution = launch { task() } // This works fine (~110-120 ms)
        measureTimeMillis {
            delay(100)
            executionCompletionSource.cancel()
            execution.join()
        }.also { elapsed -> println("Elapsed in $elapsed ms") }
    }
}

使用以下依赖关系:

代码语言:javascript
复制
implementation(kotlin("stdlib-jdk8"))
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.0.0")
implementation("io.mockk:mockk:1.8.10.kotlin13")
EN

回答 1

Stack Overflow用户

发布于 2018-11-09 20:47:51

这似乎是mockk处理协程的方式的错误-它现在是tracked here

作为一种临时的解决办法,我在需要模拟挂起函数的情况下手动创建模拟。例如:

代码语言:javascript
复制
private fun generateDummyChildren(
    numberOfChildren: Int = 5 /* sensible default */,
    executionRoutine: suspend () -> Unit
): Iterable<ExecutableNode> {
    fun createDummy(index: Int) = object: ExecutableNode {
        override val id = "Dummy $index"
        override suspend fun execute() = executionRoutine()
    }

    return Array(numberOfChildren, ::createDummy).asIterable()
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/53223093

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档