android - AndroidX.Test ActivityScenario: java.lang.AssertionError: Activity 永远不会变为请求状态“[RESUMED]”(上一个生命周期转换 =“STOPPED”)
问题描述
ActivityScenario 是 Robolectric 中的 ActivityController 和 ATSL 中的 ActivityTestRule 的替代品。
从 ATSL 重构为 AndroidX 测试时,我使用此代码在每次 espresso 测试之前启动我的 IndexActivity。
@Before
public void launchActivity() {
ActivityScenario<IndexActivity> scenario = ActivityScenario.launch(IndexActivity.class);
}
但是,我的测试在 80-90% 的时间里都停滞不前并抛出这个错误。
java.lang.AssertionError: Activity 永远不会变为请求状态“[RESUMED]”(最后一个生命周期转换 =“STOPPED”)
在尝试进行故障排除时,我将上述内容更改为:
@Before
public void launchActivity() {
ActivityScenario<IndexActivity> scenario = ActivityScenario.launch(IndexActivity.class);
scenario.moveToState(Lifecycle.State.RESUMED);
}
但是,我现在 100% 的时间都遇到同样的错误。
按照文档,我不确定为什么会这样。
我正在使用 AndroidX Test Orchestrator 并在带有 Api 28 的模拟器上进行测试
完整的 StackTrace 在这里进行测试:
10:54:42 V/InstrumentationResultParser: java.lang.AssertionError: Activity never becomes requested state "[RESUMED]" (last lifecycle transition = "STOPPED")
10:54:42 V/InstrumentationResultParser: at androidx.test.core.app.ActivityScenario.waitForActivityToBecomeAnyOf(ActivityScenario.java:228)
10:54:42 V/InstrumentationResultParser: at androidx.test.core.app.ActivityScenario.moveToState(ActivityScenario.java:368)
10:54:42 V/InstrumentationResultParser: at com.myapplication.android.test.HomeTest.launchActivity(HomeTest.java:30)
10:54:42 V/InstrumentationResultParser: at java.lang.reflect.Method.invoke(Native Method)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
10:54:42 V/InstrumentationResultParser: at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
10:54:42 V/InstrumentationResultParser: at androidx.test.internal.runner.junit4.statement.RunBefores.evaluate(RunBefores.java:76)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
10:54:42 V/InstrumentationResultParser: at androidx.test.ext.junit.runners.AndroidJUnit4.run(AndroidJUnit4.java:104)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.Suite.runChild(Suite.java:128)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.Suite.runChild(Suite.java:27)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
10:54:42 V/InstrumentationResultParser: at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
10:54:42 V/InstrumentationResultParser: at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
10:54:42 V/InstrumentationResultParser: at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
10:54:42 V/InstrumentationResultParser: at androidx.test.internal.runner.TestExecutor.execute(TestExecutor.java:56)
10:54:42 V/InstrumentationResultParser: at androidx.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:388)
10:54:42 V/InstrumentationResultParser: at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:2075)
解决方案
编辑:这现在在https://github.com/android/android-test/issues/143
声明:launch(Intent startActivityIntent)
ActivityScenario API
的方法存在限制。它等待 ActivityLifecycle.STATE.RESUMED
或DESTROYED
,如果它不在 4.5 秒内,则抛出此错误。
上下文:
我的应用程序使用IndexActivity
来加载配置,该配置指示应用程序进行某些 API 调用。但是,在它加载后立即DialogActivity
进入IndexActivity
a STOPPED
。在接受条款后,DialogActivity
返回IndexActivity
到RESUMED
然后 ActivityScenario 正常工作。在我的测试中,有一个竞争条件是 Espresso 是否可以在 4.5 秒内点击这些条款来获得结果IndexActivity
,RESUMED
或者这个错误是否会在此之前抛出。使用 ActivityScenario 启动另一个 Activity 需要进行重大重构,因此这不是一个选项。
Activity Scenario的Fix
Within public static <A extends Activity> ActivityScenario<A> launch(Intent startActivityIntent)
,检查逻辑scenario.waitForActivityToBecomeAnyOf(State.RESUMED, State.DESTROYED);
如果您可以创建自己的自定义活动场景并将这行代码调整为类似的, scenario.waitForActivityToBecomeAnyOf(State.STOPPED, State.DESTROYED);
那么理论上它对您有用。然后,您可以再次使用 ActivityScenario 将 Activity 移动到您想要的任何生命周期状态。
或者只使用旧的https://developer.android.com/reference/androidx/test/rule/ActivityTestRule,直到 Google 在 AndroidX 测试中解决这个问题。
TL;DR
发生这种情况是因为您的 Activity 的 Lifecycle.State 不是ActivityScenario.Launch()
等待的两个特定生命周期状态中的任何一个,RESUMED
或者DESTROYED
。您的活动可能是在创建 API 时未考虑的对话或其他极端情况的背景中。
推荐阅读
- javascript - Node.js - 在字符串之外使用模板文字
- react-native - 平面列表数据未显示在屏幕上
- spring - 如何使用spring boot仅将程序特定日志写入spring批处理中的文件
- powershell - Python 的 doctest 模块是否有 PowerShell 等价物?
- python - 如何将十进制数转换为具有最小值的基数?
- c# - 使用 Verlet 方法在 unity2d 中绘制火鸡
- php - 搜索字符串未在引导自动提示上传递给 php
- octobercms - 中继器内的标签
- php - 在php中运行计划任务
- android - 为什么在这些源代码中没有调用 onMeasure