使用Kotlin协程时,如何对调用暂停函数的函数进行单元测试? [英] When using kotlin coroutines, how do I unit test a function that calls a suspend function?

查看:428
本文介绍了使用Kotlin协程时,如何对调用暂停函数的函数进行单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个像这样的班

class SomeClass {
    fun someFun() {
        // ... Some synchronous code
        async {
            suspendfun() 
        }
    }

    private suspend fun suspendFun() {
         dependency.otherFun().await()
         // ... other code
    }
}

我想进行单元测试someFun(),所以我写了一个看起来像这样的单元测试:

I want to unit test someFun() so I wrote a unit test that looks like this:

@Test
fun testSomeFun() {
    runBlocking {
        someClass.someFun()
    }

    // ... verifies & asserts
}

但是这似乎不起作用,因为在完成runBlocking内部的所有操作之前,runBlocking实际上不会阻止执行.如果我直接在runBlocking内部测试suspendFun(),它会按预期工作,但是我希望能够一起测试someFun().

But this doesn't seem to work because runBlocking doesn't actually block execution until everything inside runBlocking is done. If I test suspendFun() directly inside runBlocking it works as expected but I want to be able to test someFun() all together.

有什么线索可以同时使用同步代码和异步代码测试功能吗?

Any clue how to test a function with both sync and async code?

推荐答案

修复异步

实施后,您的someFun()只会触发并忘记" async结果.结果,runBlocking在该测试中没有任何作用.

Fixing async

As implemented, your someFun() will just "fire and forget" the async result. As a result, runBlocking does not make a difference in that test.

如果可能,请使someFun()返回asyncDeferred,然后在runBlocking中调用await.

If possible, make someFun() return async's Deferred and then, in runBlocking, call await on it.

fun someFun(): Deferred<Unit> {
    // ... Some synchronous code
    return async {
        suspendFun()
    }
}

然后进行测试:

runBlocking {
    SomeClass().someFun().await()
}

问题/答案是获取更多信息的好资源.

This question/answer is a good resource for further information.

也可以避免使用suspend函数和launch创建的协程,而使用suspend:

It's also possible to avoid async in favor of using suspend functions and a launch-created coroutine:

suspend fun someFun() {
    // ... Some synchronous code
    suspendFun()
}

private suspend fun suspendFun() {
    delay(1000)
    println("executed")
    // ... other code
}

测试使用launch,而外部runBlocking隐式等待其完成:

The test uses launch and the outer runBlocking implicitly waits for its completion:

val myScope = GlobalScope
runBlocking {
    myScope.launch {
        SomeClass().someFun()
    }
}

这篇关于使用Kotlin协程时,如何对调用暂停函数的函数进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆