Compose未在60秒内进入空闲状态的Robolectric测试问题求助
Compose测试批量运行时出现AppNotIdleException的解决建议
问题场景
当UI进行异步更新(如API请求加载数据显示Lottie动画、应用筛选器更新列表)时,批量运行所有测试会抛出以下错误:
Compose did not get idle after 4303627 attempts in 60 SECONDS. Please check your measure/layout lambdas, they may be causing an infinite composition loop. Or set Espresso's master idling policy if you require a longer timeout. The following Idle Conditions failed . androidx.test.espresso.AppNotIdleException: Compose did not get idle after 4303627 attempts in 60 SECONDS. Please check your measure/layout lambdas, they may be causing an infinite composition loop. Or set Espresso's master idling policy if you require a longer timeout. The following Idle Conditions failed . at androidx.test.espresso.AppNotIdleException.create(AppNotIdleException.java:11) at androidx.compose.ui.test.junit4.RobolectricIdlingStrategy$runUntilIdle$1.invoke(RobolectricIdlingStrategy.android.kt:55) at androidx.compose.ui.test.junit4.RobolectricIdlingStrategy$runUntilIdle$1.invoke(RobolectricIdlingStrategy.android.kt:48) at androidx.compose.ui.test.junit4.AndroidSynchronization_androidKt.runOnUiThread(AndroidSynchronization.android.kt:33) at androidx.compose.ui.test.junit4.RobolectricIdlingStrategy.runUntilIdle(RobolectricIdlingStrategy.android.kt:48) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.waitForIdle(ComposeUiTest.android.kt:336) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment.access$waitForIdle(ComposeUiTest.android.kt:228) at androidx.compose.ui.test.AndroidComposeUiTestEnvironment$AndroidTestOwner.getRoots(ComposeUiTest.android.kt:529) at androidx.compose.ui.test.TestContext.getAllSemanticsNodes$ui_test_release(TestOwner.kt:85) at androidx.compose.ui.test.SemanticsNodeInteraction.fetchSemanticsNodes$ui_test_release(SemanticsNodeInteraction.kt:62) at androidx.compose.ui.test.SemanticsNodeInteraction.fetchOneOrDie(SemanticsNodeInteraction.kt:128) at androidx.compose.ui.test.SemanticsNodeInteraction.fetchSemanticsNode(SemanticsNodeInteraction.kt:79) at androidx.compose.ui.test.AndroidAssertions_androidKt.checkIsDisplayed(AndroidAssertions.android.kt:29)
解决步骤
1. 排查无限重组循环
- 检查
LaunchedEffect、derivedStateOf等触发重组的代码,确保不会在重组过程中修改触发重组的状态变量。 - 禁止在
measure/layout的lambda中修改mutableStateOf这类可观察状态,这类操作会直接引发无限循环。 - 列表筛选场景:用
remember缓存筛选后的列表实例,避免每次重组都生成新列表触发不必要的重组。
2. 管理异步操作的Idle状态
- API请求等异步任务:注册Espresso的
IdlingResource,让测试框架等待任务完成后再执行断言。 - Lottie动画:测试时可强制动画仅播放一次,或者自定义
IdlingResource监听动画的完成状态,告知测试框架何时恢复执行。
3. 调整测试超时配置
若确认无无限循环,仅因批量测试资源紧张导致超时,可延长Espresso的超时时间:
@Before fun setupTest() { // 注册Compose的Idle资源 IdlingRegistry.getInstance().register(ComposeIdlingResource) // 设置主超时为120秒 Espresso.setMasterTimeout(120, TimeUnit.SECONDS) }
4. 优化批量测试的隔离性
- 每个测试用例执行完毕后,在
@After方法中重置所有状态、取消活跃协程,避免状态残留影响后续测试。 - 避免批量测试中同时触发大量异步操作,可适当调整测试执行顺序,或添加短延迟确保前一个测试的UI状态完全稳定。
内容的提问来源于stack exchange,提问作者tinto mathew
相关产品推荐
相关产品推荐

