如何在Kotlin协程中获取可测试的虚拟时间戳?
可测试的协程时间戳获取方案
要实现一个在生产环境和runTest测试中都能正确工作的时间戳获取函数,核心是从当前协程上下文的调度器中获取时间,而非硬编码系统时间或测试专属的currentTime。以下是具体实现:
实现代码
import kotlinx.coroutines.CoroutineDispatcher import kotlinx.coroutines.ContinuationInterceptor import kotlinx.coroutines.delay import kotlinx.coroutines.test.TestDispatcher import kotlinx.coroutines.test.runTest import org.junit.Test import kotlin.test.assertThat import kotlin.test.assertEquals suspend fun getCurrentTime(): Long { // 从协程上下文获取当前调度器 val dispatcher = coroutineContext[ContinuationInterceptor] as CoroutineDispatcher return when (dispatcher) { // 测试环境下使用TestDispatcher的可控虚拟时间 is TestDispatcher -> dispatcher.currentTime // 生产环境下使用系统真实时间 else -> System.currentTimeMillis() } } @Test fun testMyCode() = runTest { delay(20) assertThat(this.currentTime).isEqualTo(20) assertThat(getCurrentTime()).isEqualTo(20) }
原理说明
- 生产环境:协程默认使用
Dispatchers.Default等标准调度器,函数会返回System.currentTimeMillis(),符合正常业务逻辑需求。 - 测试环境:
runTest会自动将协程上下文替换为TestDispatcher(如StandardTestDispatcher),该调度器的currentTime属性与TestScope.currentTime完全同步,能精准反映测试中的虚拟时间推进,不会被delay的跳过逻辑影响。
关于废弃的DelayController
DelayController被废弃后,官方推荐直接使用TestDispatcher的currentTime属性获取虚拟时间,这是当前测试协程时间的标准方式,无需再依赖废弃API。
内容的提问来源于stack exchange,提问作者Ajmal Kunnummal
相关产品推荐
相关产品推荐

