Espresso IntentsTestRule on Test with Multiple Activities

0

I am trying to stub out the Android camera's result using Espresso-Intents library.

I understand that to initialize the Espresso-Inents library I need to define a IntentsTestRule. I've defined the rule based on the first Activity that my test enters which is MainActivity.class, therefore the rule is written as such:

@Rule
public IntentsTestRule<MainActivity> mIntentsTestRules = new IntentsTestRule(MainActivity.class);

The problem is that MainActivity never loads as the system Intent to start MainActivity is being captured by Espresso-Intents..

I am receiving this exception:

java.lang.RuntimeException: Could not launch intent Intent { act=android.intent.action.MAIN flg=0x10000000 cmp=com.greenpathenergy.facilitysurveyapp/.ui.activities.MainActivity } within 45 seconds.

Moreover, as this Intent is being caught by Espresso-Intents, and I need to move from MainActivity to EditorActivity in this same @Test block, how can I allow some internal Intents through while stubbing external ones (such as when EditorActivity calls the Camera API) that fire in EditorActivity?

Thank you kindly!

android
android-intent
android-espresso
stub
ui-testing
asked on Stack Overflow May 10, 2019 by AutoM8R • edited May 10, 2019 by AutoM8R

1 Answer

1

IntentsTestRule's purpose is to solely initialize Esspresso-Intents before any tests in a @Test block are run. The IntentsTestRule simply calls Intents.init() before the @Test block and Intents.release() after the @Test block is completed.

This being said, if you would like to stub only particular Intents within a @Test block one should initialize Espresso-Intents before the action in the @Test block which fires an external (to your app's instance) Intent (such as a button click to load the camera), and release Espresso-Intents immediately after we return our stub.

This is the most simplistic approach to allowing internal Intents while stubbing external Intents.

Sample code:

@Test
public void MainActivityTest {
   // Tap the button that loads the EditorActivity from MainActivity
   onView(withId(R.id.btn_load_editor_activity)).perform(click());

   // Initialize Espresso-Intents library to capture the external Intent to the camera API 
    Intents.init();

    // ActivityResult will be provided as a stub result for the camera API's natural result
    // Note: I've ignored the bitmap creation and instead used null for simplicity, you will
    // want to mock the bitmap here by creating a fake picture as the resultData
    ActivityResult result = new ActivityResult(Activity.RESULT_OK, null);

    // Notify Espresso the stub result above should be provided when it sees an Intent to load the camera API
    intending(toPackage("com.android.camera2")).respondWith(result);

    // Simulate a button tap of the button that loads the camera API, the stub will be automatically returned as the result immediately
    // instead of the camera API opening and sending back its result
    onView(withId(R.id.btn_take_placard_photo)).perform(click());

    // Release the Espresso-Intents library to allow other internal Intents to work as intended without being intercepted by Espresso-Intents
    Intents.release();
}

I hope you find this helpful!

answered on Stack Overflow May 10, 2019 by AutoM8R

User contributions licensed under CC BY-SA 3.0