Flow 单元测试 (Turbine)
虽然 runTest 配合 toList 可以测试简单的 Flow,但对于复杂的流(尤其是热流、错误处理),Google 官方推荐使用 CashApp 开源的 Turbine 库。
依赖配置
kotlin
dependencies {
testImplementation("app.cash.turbine:turbine:1.0.0")
}核心 API: test
Turbine 提供了一个 test 扩展函数,将流的收集过程转变为类似“队列”的挂起操作。
kotlin
@Test
fun testSimpleFlow() = runTest {
flowOf("A", "B").test {
// 依次断言发射的元素
assertEquals("A", awaitItem())
assertEquals("B", awaitItem())
// 断言流正常结束
awaitComplete()
}
}测试异常
kotlin
@Test
fun testError() = runTest {
flow {
emit(1)
throw RuntimeException("Boom!")
}.test {
assertEquals(1, awaitItem())
// 断言异常
val error = awaitError()
assertEquals("Boom!", error.message)
}
}配合 Hot Flow (StateFlow)
测试 StateFlow 时,Turbine 特别有用,因为它可以跳过中间值(如果是 SharedFlow)或只关注最新的状态。
kotlin
@Test
fun testViewModel() = runTest {
val viewModel = MyViewModel()
// 开始观察状态
viewModel.uiState.test {
// 初始状态
assertEquals(UiState.Loading, awaitItem())
// 触发业务逻辑
viewModel.loadData()
// 验证后续状态
assertEquals(UiState.Success, awaitItem())
}
}忽略剩余元素
有时我们只关心前几个值,不想处理 awaitComplete。可以使用 cancelAndIgnoreRemainingEvents。
kotlin
infiniteFlow.test {
assertEquals(1, awaitItem())
cancelAndIgnoreRemainingEvents() // 退出测试块
}