AndroidX.Test ActivityScenario: java.lang.AssertionError: Activity never becomes requested state "[RESUMED]" (last lifecycle transition = "STOPPED")
Asked Answered
H

3

14

ActivityScenario is a replacement of ActivityController in Robolectric and ActivityTestRule in ATSL.

When refactoring from ATSL to AndroidX Test, I am using this code to start my IndexActivity before each espresso test.

    @Before
public void launchActivity() {
    ActivityScenario<IndexActivity> scenario = ActivityScenario.launch(IndexActivity.class);
}

However, my tests are stalling out 80-90% of the time and throwing this error.

java.lang.AssertionError: Activity never becomes requested state "[RESUMED]" (last lifecycle transition = "STOPPED")

When trying to troubleshoot, I changed the above to:

@Before
public void launchActivity() {
    ActivityScenario<IndexActivity> scenario = ActivityScenario.launch(IndexActivity.class);
    scenario.moveToState(Lifecycle.State.RESUMED);
}

However, I am now getting the same error 100% of the time.

Following the documentation, I am not sure why this is happening.

I am using AndroidX Test Orchestrator and testing on an Emulator with Api 28

Full StackTrace for Test here:

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)
Hymanhymen answered 3/12, 2018 at 16:55 Comment(0)
H
9

EDIT: This is now fixed in https://github.com/android/android-test/issues/143

Claim: There is a limitation within the launch(Intent startActivityIntent) method of the ActivityScenario API. It waits for the Activity to be Lifecycle.STATE.RESUMED or DESTROYED and if it isn't within 4.5 seconds then it throws this error.

Context: My application uses an IndexActivity to load a config which instructs the application on certain API calls to make. However, immediately after it loads a DialogActivity and the IndexActivity goes into STOPPED. On accepting terms within the DialogActivity the IndexActivity goes back into RESUMED and then ActivityScenario works properly. With my tests, there was a race condition on whether Espresso could click through the terms within 4.5 seconds to get the IndexActivity to be RESUMED or whether this error would throw before that. It would take major refactoring to enable another Activity to be launched with ActivityScenario so that was not an option.

The Fix Within public static <A extends Activity> ActivityScenario<A> launch(Intent startActivityIntent) of Activity Scenario, check the logic scenario.waitForActivityToBecomeAnyOf(State.RESUMED, State.DESTROYED);

If you can create your own custom Activity Scenario and adjust this line of code to be something like scenario.waitForActivityToBecomeAnyOf(State.STOPPED, State.DESTROYED); then it will theoretically work for you. You can then use ActivityScenario again to move the Activity into whatever Lifecycle State you want.

OR just use the old https://developer.android.com/reference/androidx/test/rule/ActivityTestRule until Google addresses this in AndroidX Test.

TL;DR This is happening because the Lifecycle.State of your Activity is not either of the two specific lifecycle states ActivityScenario.Launch() waits for, RESUMED or DESTROYED. Your activity is probably in the background of a dialog or another edge-case situation that was not thought about when creating the API.

Hymanhymen answered 5/12, 2018 at 18:15 Comment(1)
Hey Mark! Can this be accepted as the answer? looks like updated androidx.test fixed the issue.Olecranon
B
2

For me this was because I had a device plugged in with the screen off and an emulator running. I assumed I was launching to the emulator but I was running it on the device. Since the screen was off, the test was never able to transition to a valid state.

Brandebrandea answered 30/6, 2020 at 19:6 Comment(1)
Same to me. I expected the screen will turn on automatically, but it is not.Tula
M
0

For the record, this will be fixed in upcoming release. https://github.com/android/android-test/issues/143

Movable answered 20/12, 2018 at 2:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.