使用 kotlin 协程时,如何对调用挂起函数的函数进行单元测试?
When using kotlin coroutines, how do I unit test a function that calls a suspend function?
我有一个class这样的
class SomeClass {
fun someFun() {
// ... Some synchronous code
async {
suspendfun()
}
}
private suspend fun suspendFun() {
dependency.otherFun().await()
// ... other code
}
}
我想进行单元测试 someFun()
所以我写了一个如下所示的单元测试:
@Test
fun testSomeFun() {
runBlocking {
someClass.someFun()
}
// ... verifies & asserts
}
但这似乎不起作用,因为在 runBlocking 中的所有内容完成之前,runBlocking 不会真正阻止执行。如果我直接在 runBlocking
中测试 suspendFun()
,它会按预期工作,但我希望能够一起测试 someFun()
。
知道如何使用同步代码和异步代码测试函数吗?
修复异步
实施后,您的 someFun()
将“触发并忘记” async
结果。因此,runBlocking
对该测试没有影响。
如果可能,制作someFun()
returnasync
的Deferred
,然后在runBlocking
中调用await
就可以了。
fun someFun(): Deferred<Unit> {
// ... Some synchronous code
return async {
suspendFun()
}
}
然后测试:
runBlocking {
SomeClass().someFun().await()
}
这个 是获取更多信息的好资源。
备选方案:使用启动
也可以避免 async
而使用 suspend
函数和 launch
创建的协程:
suspend fun someFun() {
// ... Some synchronous code
suspendFun()
}
private suspend fun suspendFun() {
delay(1000)
println("executed")
// ... other code
}
测试使用 launch
并且外部 runBlocking
隐式等待其完成:
val myScope = GlobalScope
runBlocking {
myScope.launch {
SomeClass().someFun()
}
}
我有一个class这样的
class SomeClass {
fun someFun() {
// ... Some synchronous code
async {
suspendfun()
}
}
private suspend fun suspendFun() {
dependency.otherFun().await()
// ... other code
}
}
我想进行单元测试 someFun()
所以我写了一个如下所示的单元测试:
@Test
fun testSomeFun() {
runBlocking {
someClass.someFun()
}
// ... verifies & asserts
}
但这似乎不起作用,因为在 runBlocking 中的所有内容完成之前,runBlocking 不会真正阻止执行。如果我直接在 runBlocking
中测试 suspendFun()
,它会按预期工作,但我希望能够一起测试 someFun()
。
知道如何使用同步代码和异步代码测试函数吗?
修复异步
实施后,您的 someFun()
将“触发并忘记” async
结果。因此,runBlocking
对该测试没有影响。
如果可能,制作someFun()
returnasync
的Deferred
,然后在runBlocking
中调用await
就可以了。
fun someFun(): Deferred<Unit> {
// ... Some synchronous code
return async {
suspendFun()
}
}
然后测试:
runBlocking {
SomeClass().someFun().await()
}
这个
备选方案:使用启动
也可以避免 async
而使用 suspend
函数和 launch
创建的协程:
suspend fun someFun() {
// ... Some synchronous code
suspendFun()
}
private suspend fun suspendFun() {
delay(1000)
println("executed")
// ... other code
}
测试使用 launch
并且外部 runBlocking
隐式等待其完成:
val myScope = GlobalScope
runBlocking {
myScope.launch {
SomeClass().someFun()
}
}