如何在单元测试中跳过Kotlin协程runBlocking内的delay?
解决kotlinx.coroutines.test无法跳过runBlocking内delay的问题
问题原因
runTest提供的TestDispatcher仅能接管其自身作用域内启动的协程调度逻辑。而被测方法中的runBlocking会创建独立的协程作用域,使用默认的阻塞事件循环执行delay,完全不受TestDispatcher的控制,因此无法跳过延迟。
解决方案:静态Mock delay函数
通过MockK工具静态拦截kotlinx.coroutines.delay函数的调用,让它直接返回而不执行实际等待。这种方式不需要修改被测代码,就能跳过所有位置的delay调用。
测试代码示例
import io.mockk.every import io.mockk.mockkStatic import io.mockk.unmockkStatic import kotlinx.coroutines.delay import kotlinx.coroutines.test.runTest import org.junit.jupiter.api.AfterEach import org.junit.jupiter.api.Test class DelayTest { @Test fun testDelaySkipped() = runTest { // 静态mock delay函数 mockkStatic(kotlinx.coroutines.delay::class) // 让所有delay调用直接返回,不等待 every { delay(any<Long>()) } returns Unit // 调用被测方法 delayTest() // 这里添加你的断言逻辑 } @AfterEach fun cleanUp() { // 清理mock,避免影响其他测试 unmockkStatic(kotlinx.coroutines.delay::class) } } // 不可修改的被测代码 fun delayTest() { runBlocking { delay(3000L) // 业务逻辑 } }
关键说明
mockkStatic会拦截所有对kotlinx.coroutines.delay的调用,无论它处于哪个协程作用域内。every { delay(any<Long>()) } returns Unit指定了delay函数的行为:不管传入多少延迟时间,都直接返回,不执行实际等待。- 测试结束后必须调用
unmockkStatic清理mock,防止对其他测试用例产生副作用。
内容的提问来源于stack exchange,提问作者firstpostcommenter
相关产品推荐
相关产品推荐

