You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在单元测试中跳过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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 18:27:21