Jetpack Compose中如何通过屏幕旋转测试rememberSaveable功能
问题核心原因
你仅调用uiAutomation.setRotation修改系统旋转状态,没有触发Activity的配置变更重建流程。remember存储的值依附于当前Compose Composition实例,只有Activity重建、界面重新组合时,remember的值才会被重置,rememberSaveable的值才会从SavedState中恢复。你的测试中界面从未走重建逻辑,自然会出现两个值同时存在的异常结果。
解决步骤
- 首先确认测试使用的Activity未在AndroidManifest中配置
android:configChanges="orientation|screenSize",该配置会拦截屏幕旋转对应的配置变更,不会触发Activity重建。 - 建议使用
createAndroidComposeRule而非默认的createComposeRule,避免默认生成的ComponentActivity存在隐藏配置影响测试结果。 - 修改旋转后的等待逻辑,不要仅依赖
waitForIdleSync,需要主动等待Activity重建完成、Compose界面完成重组后再执行断言。
修改后可正常运行的测试代码
@RunWith(AndroidJUnit4::class) class SavingTurnTest { @get:Rule val composeTestRule = createAndroidComposeRule<ComponentActivity>() @Before fun setUp(){ composeTestRule.setContent{ MyApplicationTheme { SampleRemember_saveable() } } composeTestRule.onNodeWithTag("remember").performTextInput("Text_Remember") composeTestRule.onNodeWithTag("saveable").performTextInput("Text_Saveable") composeTestRule.waitForIdle() } @Test fun saveTextOnTurn(){ val uiAutomation = InstrumentationRegistry.getInstrumentation().uiAutomation // 锁定初始竖屏状态 uiAutomation.setRotation(ROTATION_FREEZE_0) // 切换到横屏触发配置变更 uiAutomation.setRotation(ROTATION_FREEZE_90) // 等待5秒,直到确认界面重建完成(output节点重新加载) composeTestRule.waitUntil(timeoutMillis = 5000) { composeTestRule.onAllNodesWithTag("output").fetchSemanticsNodes().isNotEmpty() } // 此时断言符合预期 composeTestRule.onNodeWithTag("output").assertTextDoesNotContain("Text_Remember") composeTestRule.onNodeWithTag("output").assertTextContains("Text_Saveable") composeTestRule.onNodeWithTag("output").assertTextEquals("Text_Saveable") } }
替代高稳定性方案
如果你不需要严格模拟旋转操作,只需要验证remember和rememberSaveable的行为差异,可以直接调用composeTestRule.activityScenario.recreate()主动触发Activity重建,省去旋转相关的等待逻辑,测试运行速度和稳定性都会更高。
内容的提问来源于stack exchange,提问作者Nighty2010
相关产品推荐
相关产品推荐

