Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Application choosers - Android Espresso unit tests breaking after opening external URL

I have an Android App with a login screen, which also contains a forgot password button that brings you to a website for further assistance. I'm testing it using Spoon and Espresso, with the following simple test function:

@Test
public void testForgotPassword()
{
    onView(withId(R.id.login_forgot_password)).perform(click());

    intended(allOf(
            hasAction(Intent.ACTION_VIEW),
            hasData(BuildConfig.FORGOT_PW_URL)));
}

This test passes fine, and shows the "Complete action using browser/chrome dialog" on the screen, which is the correct behaviour for this device. All good so far. However, as long as that dialog remains there, any subsequent test fails to open the app, returning an exception after a long pause and failing the test.

How can I update the test to actively get rid of the dialog, or otherwise make sure I can continue with the remainder of my unit tests?

The full exception for your reference:

2016-04-21 17:37:04 [STRL.testFailed] failed java.lang.RuntimeException: Could not launch intent Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=nl.test.example/.ui.activity.login.LoginActivity_ } within 45 seconds. Perhaps the main thread has not gone idle within a reasonable amount of time? There could be an animation or something constantly repainting the screen. Or the activity is doing network calls on creation? See the threaddump logs. For your reference the last time the event queue was idle before your activity launch request was 1461252979050 and now the last time the queue went idle was: 1461252979050. If these numbers are the same your activity might be hogging the event queue.
  at android.support.test.runner.MonitoringInstrumentation.startActivitySync(MonitoringInstrumentation.java:360)
  at android.support.test.rule.ActivityTestRule.launchActivity(ActivityTestRule.java:219)
  at android.support.test.rule.ActivityTestRule$ActivityStatement.evaluate(ActivityTestRule.java:268)
  at org.junit.rules.RunRules.evaluate(RunRules.java:20)
  at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
  at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
  at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
  at org.junit.runners.Suite.runChild(Suite.java:128)
  at org.junit.runners.Suite.runChild(Suite.java:27)
  at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
  at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
  at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
  at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
  at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
  at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
  at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
  at org.junit.runner.JUnitCore.run(JUnitCore.java:115)
  at android.support.test.internal.runner.TestExecutor.execute(TestExecutor.java:59)
  at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:262)
  at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1667)
like image 703
Combuster Avatar asked Dec 18 '22 17:12

Combuster


1 Answers

You have to stub all external intents to be able to proceed with your test cases. Put this peace of code in your test class:

@Before
public void stubAllExternalIntents() {
    // By default Espresso Intents does not stub any Intents. Stubbing needs to be setup before
    // every test run. In this case all external Intents will be blocked.
    intending(not(isInternal())).respondWith(new ActivityResult(Activity.RESULT_OK, null));
}

More here - IntentsBasicSample.

like image 131
denys Avatar answered Jan 05 '23 00:01

denys