✨ ComposeTestRule 是 Compose 单元测试的基石。三个核心工厂方法各有专攻,理解它们的区别能让你在测试中游刃有余。本课用最直观的方式拆解它们的使用场景。
最常用的规则,不依赖 Android 环境,在 JVM 上即可运行。适合测试 Composable 函数、组件状态、交互等。
继承 ActivityScenarioRule,在真实 Android 环境中测试。适用于依赖 Context、资源、主题、导航等场景。
不自动注册任何 Composable,需要你手动调用 setContent。适合完全自定义的测试环境或特殊设置。
| 特性 | createComposeRule | createAndroidComposeRule | createEmptyComposeRule |
|---|---|---|---|
| 测试环境 | 纯 JVM / Robolectric | Android 仪器化 (Activity) | 纯 JVM / 任意 |
| 自动 setContent | ✅ 是 (空 Compose) | ✅ 是 (绑定 Activity) | ❌ 否 (需手动) |
| 访问 Context/资源 | ⚠️ 有限 (Robolectric) | ✅ 完整 | ❌ 无 (除非手动提供) |
| 启动速度 | ⚡ 快 | 🐢 中等 (需启动 Activity) | ⚡ 最快 |
| 典型场景 | 组件逻辑、状态测试 | UI 集成、导航、主题 | 自定义测试容器、多 content |
测试一个简单的 Greeting 组件,不涉及 Android 资源,快速验证状态与交互。
@get:Rule
val composeTestRule = createComposeRule()
@Test
fun greeting_displaysName() {
composeTestRule.setContent {
Greeting(name = "小明")
}
composeTestRule.onNodeWithText("你好, 小明!").assertExists()
}
测试使用 stringResource 或主题颜色的 Composable,需要真实 Context。
@get:Rule
val androidRule = createAndroidComposeRule<MainActivity>()
@Test
fun appBar_usesCorrectTitle() {
androidRule.onNodeWithText(
androidRule.activity.getString(R.string.app_name)
).assertIsDisplayed()
}
需要多次 setContent 或注入特殊父容器时使用。
@get:Rule
val emptyRule = createEmptyComposeRule()
@Test
fun customWrapper() {
emptyRule.setContent {
MyTheme {
Button(onClick = { }) { Text("确定") }
}
}
emptyRule.onNodeWithText("确定").assertHasClickAction()
}