62

the following is one of my Espresso test cases.

    public void testLoginAttempt() {
        Espresso.onView(ViewMatchers.withId(R.id.username)).perform(ViewActions.clearText()).perform(ViewActions.typeText("nonexistinguser@krossover.com"));
        Espresso.onView(ViewMatchers.withId(R.id.username)).perform(ViewActions.clearText()).perform(ViewActions.typeText("invalidpassword"));

        Espresso.onView(ViewMatchers.withId(R.id.login_button)).perform(ViewActions.click());
        // AFTER CLICKING THE BUTTON, A NEW ACTIVITY WILL POP UP.
        // Clicking launches a new activity that shows the text entered above. You don't need to do
        // anything special to handle the activity transitions. Espresso takes care of waiting for the
        // new activity to be resumed and its view hierarchy to be laid out.
        Espresso.onView(ViewMatchers.withId(R.id.action_logout))
                .check(ViewAssertions.matches(not(ViewMatchers.isDisplayed())));

    }

Currently what I did was to check if a view in the new activity (R.id.action_logout) is visibible or not. If visible, I will assume tha the activity opened successfully. But it doesn't seem to work as I expected. Is there a better way to check if a new activity is successfully launched instead of checking a view in that activity is visible? Thanks

tomrozb
  • 25,773
  • 31
  • 101
  • 122
user2062024
  • 3,541
  • 7
  • 33
  • 44

8 Answers8

79

You can use:

intended(hasComponent(YourExpectedActivity.class.getName()));

Requires this gradle entry:

androidTestCompile ("com.android.support.test.espresso:espresso-intents:$espressoVersion")

The import for the intended() and hasComponent()

import static android.support.test.espresso.intent.Intents.intended;
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent;

as mentioned by Shubam Gupta please remember to call Intents.init() before calling intended(). You can eventually call it in the @Before method.

kingston
  • 11,053
  • 14
  • 62
  • 116
baskara
  • 1,256
  • 11
  • 7
  • 1
    hmm, nowadays android official docs don't mention the `Intents.init()` thing, and in my single case it works perfectly without this. What's the proper solution then? – Antek Dec 13 '18 at 14:04
  • Finally, you need to release `Intents` in within `@After` like `Intents.release()` – dgngulcan Sep 16 '19 at 17:53
  • If you are new to this, be sure to read Shubhams answer below also. – DavidR Jan 13 '21 at 04:40
  • 1
    If you already migrated to AndroidX then it's `androidTestImplementation "androidx.test.espresso:espresso-intents:3.4.0"` – Adam Burley Aug 23 '22 at 14:12
  • import statement for androidx is `androidx.test.espresso.intent.Intents.intended` – ganjaam Mar 04 '23 at 10:39
25

Try:

intended(hasComponent(YourActivity.class.getName()));

Also, keep in mind

java.lang.NullPointerException is thrown if Intents.init() is not called before intended()

Shubham Gupta
  • 424
  • 5
  • 4
12

You may do it as follows:

    @Test
public void testLoginAttempt() {
    Espresso.onView(ViewMatchers.withId(R.id.username)).perform(ViewActions.clearText()).perform(ViewActions.typeText("nonexistinguser@example.com"));
    Espresso.onView(ViewMatchers.withId(R.id.username)).perform(ViewActions.clearText()).perform(ViewActions.typeText("invalidpassword"));

    Intents.init();
    Espresso.onView(ViewMatchers.withId(R.id.login_button)).perform(ViewActions.click());
    Intents.release();
}

java.lang.NullPointerException is thrown if Intents.init() is not called.

dsh
  • 12,037
  • 3
  • 33
  • 51
Abdul Wadood
  • 1,161
  • 1
  • 10
  • 18
10

The problem is that your application performs the network operation after you click login button. Espresso doesn't handle (wait) network calls to finish by default. You have to implement your custom IdlingResource which will block the Espresso from proceeding with tests until IdlingResource returns back in Idle state, which means that network request is finished. Take a look at Espresso samples page - https://google.github.io/android-testing-support-library/samples/index.html

denys
  • 6,834
  • 3
  • 37
  • 36
10

Make sure the Espresso intent library is in the gradle dependencies

androidTestImplementation "com.android.support.test.espresso:espresso-intents:3.0.1"

Then import these two in your test file

import static android.support.test.espresso.intent.Intents.intended
import static android.support.test.espresso.intent.matcher.IntentMatchers.hasComponent

Then add IntentsTestRule in your test class

@Rule
@JvmField
val mainActivityRule = IntentsTestRule(MainActivity::class.java)

Finally check the activity has launched intent

@Test
fun launchActivityTest() {
    onView(ViewMatchers.withId(R.id.nav_wonderful_activity))
            .perform(click())

    intended(hasComponent(WonderfulActivity::class.java!!.getName()))
}
Community
  • 1
  • 1
s-hunter
  • 24,172
  • 16
  • 88
  • 130
  • 1
    IntentsTestRule is deprecated rigth now. You should use Intents.init() as mentioned above in conjunction with ActivityScenarioRule. – Andy Sep 02 '21 at 15:02
  • If you already migrated to AndroidX then it's `androidTestImplementation "androidx.test.espresso:espresso-intents:3.4.0"` – Adam Burley Aug 23 '22 at 14:11
7

Try with

intended(hasComponent(new ComponentName(getTargetContext(), ExpectedActivity.class)));

Look at response from @riwnodennyk

Community
  • 1
  • 1
lujop
  • 13,504
  • 9
  • 62
  • 95
0

I use this approach:

// The IntentsTestRule class initializes Espresso Intents before each test, terminates the host activity, and releases Espresso Intents after each test
    @get:Rule
    var tradersActivity: IntentsTestRule<TradersActivity> = IntentsTestRule(TradersActivity::class.java)
    @get:Rule
    var jsonViewActivity: IntentsTestRule<JsonViewActivity> = IntentsTestRule(JsonViewActivity::class.java)

    @Test
    fun scrollToItemAndClick() {
     onView(withId(R.id.tradersRecyclerView)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(ITEM_POS, click()))

        // check is activity was started
        intended(hasComponent(JsonViewActivity::class.java.getName()))
    }
Alexei
  • 14,350
  • 37
  • 121
  • 240
-8
@RunWith(RobolectricTestRunner.class)
public class WelcomeActivityTest {

    @Test
    public void clickingLogin_shouldStartLoginActivity() {
        WelcomeActivity activity = Robolectric.setupActivity(WelcomeActivity.class);
        activity.findViewById(R.id.login).performClick();

        Intent expectedIntent = new Intent(activity, LoginActivity.class);
        assertThat(shadowOf(activity).getNextStartedActivity()).isEqualTo(expectedIntent);
    }
}