第 15 课2026.07.31
共享状态持有者决定 Android 和 iOS 最终看到的页面状态。把测试写在 commonTest,可以用一套用例验证两端共同依赖的状态转换,不需要启动模拟器或访问真实服务器。
第 15 课:测试共享状态持有者
- 日期:2026-07-31
- 课程序号:15
- 知识点:使用 Fake Repository 和
runTest验证共享状态
用途
共享状态持有者决定 Android 和 iOS 最终看到的页面状态。把测试写在 commonTest,可以用一套用例验证两端共同依赖的状态转换,不需要启动模拟器或访问真实服务器。
核心概念
- 测试向
UserStore注入可控的 Fake Repository。 runTest用来执行包含挂起函数的协程测试。- 通过
state.value检查当前StateFlow状态。 - 测试关注输入和可观察结果,不读取私有
_state。 - 成功与失败应分别验证,避免只覆盖理想链路。
示例代码
commonTest 需要 Kotlin 测试和协程测试依赖:
kotlin
kotlin {
sourceSets {
commonTest.dependencies {
implementation(kotlin("test"))
implementation(libs.kotlinx.coroutines.test)
}
}
}准备一个返回固定结果的 Fake:
kotlin
class FakeUserRepository(
private val result: DataResult<User>,
) : UserRepository {
override suspend fun loadUser(id: Long): DataResult<User> {
return result
}
}commonTest/UserStoreTest.kt:
kotlin
import kotlinx.coroutines.test.runTest
import kotlin.test.Test
import kotlin.test.assertEquals
class UserStoreTest {
@Test
fun startsWithIdleState() {
val repository = FakeUserRepository(
DataResult.Failure(DataError.Network),
)
val store = UserStore(repository)
assertEquals(UserUiState.Idle, store.state.value)
}
@Test
fun exposesContentAfterSuccessfulLoad() = runTest {
val user = User(
id = 1L,
displayName = "Ada",
)
val repository = FakeUserRepository(
DataResult.Success(user),
)
val store = UserStore(repository)
store.load(id = 1L)
assertEquals(
UserUiState.Content(user),
store.state.value,
)
}
}Fake 返回确定数据,因此测试结果稳定,也能证明 UserStore 的状态来自 Repository 结果。
5 分钟练习
增加一个测试:Fake Repository 返回 DataError.Network,执行 load() 后验证状态为 UserUiState.Error(DataError.Network)。
参考答案
kotlin
@Test
fun exposesErrorAfterFailedLoad() = runTest {
val repository = FakeUserRepository(
DataResult.Failure(DataError.Network),
)
val store = UserStore(repository)
store.load(id = 1L)
assertEquals(
UserUiState.Error(DataError.Network),
store.state.value,
)
}测试直接验证数据层错误是否被正确映射,不需要让 UI 根据空内容判断失败。
与上一课的联系
上一课建立了 UserStore 和统一 UserUiState;本课利用此前学习的构造器注入与 Fake,验证 Repository 的成功、失败结果会变成正确的共享状态。