跳转到正文
YGJoon
返回

Android Kotlin 协程测试与调试技巧

编辑文章

测试工具包

Gradle 依赖:

testImplementation("org.jetbrains.kotlinx:kotlinx-coroutines-test:1.8.1")
testImplementation("app.cash.turbine:turbine:1.1.0")

单元测试示例

@OptIn(ExperimentalCoroutinesApi::class)
class HomeViewModelTest {
    private val dispatcher = StandardTestDispatcher()

    @Before
    fun setup() {
        Dispatchers.setMain(dispatcher)
    }

    @After
    fun tearDown() {
        Dispatchers.resetMain()
    }

    @Test
    fun `refresh success`() = runTest {
        val repository = FakeRepository(result = Result.success(listOf("A")))
        val viewModel = HomeViewModel(repository)

        viewModel.refresh()
        dispatcher.scheduler.advanceUntilIdle()

        assertEquals(listOf("A"), viewModel.state.value.items)
    }
}

Flow 测试

@Test
fun `state emits loading then success`() = runTest {
    val flow = repository.observeState()
    flow.test {
        assertEquals(State.Loading, awaitItem())
        assertTrue(awaitItem() is State.Success)
        cancelAndIgnoreRemainingEvents()
    }
}

调试技巧

1. 协程调试器

2. 日志追踪

val coroutineExceptionHandler = CoroutineExceptionHandler { _, throwable ->
    Timber.e(throwable, "Coroutine error")
}

viewModelScope.launch(coroutineExceptionHandler) {
    // ...
}

3. 调度器标签

DebugProbes.install()
DebugProbes.dumpCoroutines(PrintWriter(System.out))

常见问题排查

问题原因排查步骤
协程未取消Job 未保存在作用域检查 viewModelScope、launch 返回值
测试卡住使用真实调度器 + 延迟替换为 TestDispatcher,使用 advanceUntilIdle()
Flow 未触发缺少收集者检查 collect 位置,确认未忘记 collect
线程切换异常调度器混用使用 withContext 明确线程切换

最佳实践

  1. 所有 ViewModel 协程统一使用 viewModelScope。
  2. 对 launch 结果命名保存,用于取消或测试。
  3. 在测试中使用 runTest + StandardTestDispatcher 控制时间。
  4. 使用 assertThrows 验证错误场景,确保异常路径覆盖。

总结

协程调试需要结合 IDE 工具与日志追踪;测试阶段通过 kotlinx-coroutines-test 可以模拟时间、线程环境。建立标准调试流程与测试模板,有助于快速定位并发问题,提升协程相关代码的可靠性。


编辑文章
分享这篇文章:

上一篇
Android Kotlin 多模块资源与路由管理
下一篇
Android Kotlin 协程基础与调度器