Espresso IntentsTestRule on Test with Multiple Activities

Issue

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 { actandroid.intent.action.MAIN flg0x10000000 cmpcom.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!

Solution

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 By – AutoM8R

Leave a Comment