我正在尝试跳过运行单元测试时的延迟。
我从kotlinx.coroutines.test中找到了关于runTest
的信息,但是它不起作用。
代码中有什么错误?代码等待3秒钟而不是跳过延迟。
代码:
import kotlinx.coroutines.delay
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.mockito.junit.jupiter.MockitoExtension
import java.time.LocalDateTime
import kotlinx.coroutines.test.runTest
import kotlinx.coroutines.*
import org.mockito.Mockito.*
@ExtendWith(MockitoExtension::class)
class KotlinTestSkipDelay {
@OptIn(ExperimentalCoroutinesApi::class)
@Test
fun `skip delay`() {
runTest {
println("start")
println(LocalDateTime.now())
delayTest()
println("end")
println(LocalDateTime.now())
}
}
private fun delayTest() { //System under test so cannot change
runBlocking {
delay(3000L)
}
}
}
我的应用程序中的实际代码需要一个延迟,所以它使用runBlocking()。没有suspend
函数,并且delay()是从一个普通方法调用的,不在协程范围内。类似于单元测试中显示的delayTest()
方法。在测试此代码时,我如何跳过此延迟?
3条答案
按热度按时间aor9mmx11#
这里的问题是你在
delayTest()
中使用了runBlocking()
,它启动了一个全新的协程,它不知道runTest()
,正如函数runBlocking()
的名字所暗示的,它阻塞了当前线程。问题的解决方案取决于你的具体情况。上面的代码看起来像是重现问题的最小示例,所以你的具体情况可能会复杂得多。但是一般来说,如果
delayTest()
是从协程调用的,并且它要等待某个东西,那么它应该是一个suspend函数,并且永远不应该阻塞:如果你在代码中使用
runBlocking()
,可能会从协程调用它,那么你可能会遇到比这更大的问题,包括降低性能甚至在运行时出现死锁。这就是为什么通常不鼓励在代码中使用runBlocking()
的原因之一。g6ll5ycj2#
单元测试必须模拟除了被测单元之外的所有东西。如果被测单元在其逻辑中添加了一些延迟,那么就没有什么可做的了,你能做的最好的事情就是在那里检查你的逻辑,也许你做错了什么,也许你可以通过添加延迟的单元来解耦你的测试单元。在那之后,你将能够模拟添加延迟的单元,并从那里删除延迟。
一般来说,这样做的目的是使我们的逻辑对单元测试更友好:)
6qftjkof3#
您需要使用TestCoroutineScheduler。请阅读以下内容:https://kt.academy/article/cc-testing
编辑:基于注解的示例代码: