103

I am trying to test the absence of the UI view. The view selector is as follows:

public static ViewInteraction onMyTestUi() {
    return onView(withId(R.id.myTestId));
}

The selector works fine to check if the view is displayed, but gives error on checking if the view not displayed. I am using this as follows:

 onMyTestUi().check(matches(not(isDisplayed())));

But I get the following error:

com.google.android.apps.common.testing.ui.espresso.NoMatchingViewException: No views in hierarchy found matching: with id: is If the target view is not part of the view hierarchy, you may need to use Espresso.onData to load it from one of the following AdapterViews:android.widget.ListView{...}

This is strange. I am checking the absence of the UI and its expected that this view won't be found. Then why Espresso is throwing error? Please suggest what might be going wrong here.

user846316
  • 6,037
  • 6
  • 31
  • 40

5 Answers5

194

Need to use doesNotExist() instead. Found here.

If the view is there in the view hierarchy but in an invisible state (visibility is set to 'INVISIBLE'), use not(isDisplayed). However, if the view is not there at all in the view hierarchy (e.g. visibility set to 'GONE'), doesNotExist() is used.

Community
  • 1
  • 1
user846316
  • 6,037
  • 6
  • 31
  • 40
  • 19
    It doesn't work for me, but `onView(withId(R.id.myTestId)).check(matches(not(isDisplayed())));` did work. – Sithu Apr 21 '16 at 05:39
  • 42
    @Sithu -It depends on the app. If the view you’re looking for is there in the view hierarchy but invisible, then you need to use not(isDisplayed). However, if the view is not there in the view hierarchy, you need to use doesNotExist(). – user846316 Apr 21 '16 at 11:42
  • 1
    I have the button in layout, but set visibility `View.GONE` in `onCreate` upon user role. So, does it mean that it is in the view hierarchy and invisible? – Sithu Apr 22 '16 at 02:31
  • Yeah! Thanks for this, super solved my problem, and makes my morning much better (went to bed with this issue). – Booger Jun 06 '18 at 15:23
  • 1
    If the view is gone from the view hierarchy—which can happen when an action caused a transition to another activity—you should use ViewAssertions.doesNotExist(): View.GONE example in your example is wrong and misleading. Please edit your answer – metis Jul 16 '20 at 10:17
  • @metis and then how does the answer above makes it misleading? View.GONE is one of the examples when doesNotExist() can be used. Please try again. Thanks. – user846316 Jul 16 '20 at 11:58
  • 2
    View.GONE works with not(isDisplayed() but does not work with doesNotExist(). doesNotExist returns true if visibility is GONE. I tried with example. In the link you gave there is nothing said related to View.GONE. – metis Jul 16 '20 at 16:03
  • Pabel's answer works for me but this answer does not. Mabye I'm doing something wrong and an actual example of the code would help – Nick Aug 23 '22 at 16:55
21

Also work with yours method, but something like this:

onView(withId(R.id.next)).check(matches(not(isDisplayed())));
Morozov
  • 4,968
  • 6
  • 39
  • 70
18
onView(withText("")).check(doesNotExist());
spenibus
  • 4,339
  • 11
  • 26
  • 35
Olivia Liao
  • 375
  • 3
  • 7
  • 7
    This is a partially correct answer. This will only work if targedet view does not exist in the layout (view hierarchy does not contain this view.) However, this assertion will fail if targeted view actually exists in the layout view hierarchy, but it's visibility state is GONE or INVISIBLE. Assertion failure message in that case will state: `android.support.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: View is present in the hierarchy...` – Simon-Droid Dec 29 '16 at 15:46
  • Correct, so I think you could check the error message with the detailed view hierarchy. – Olivia Liao Dec 29 '16 at 19:54
14

You can try this option if you check the view visibility "withEffectiveVisibility"

    onView(withId(R.id.YOURVIEW)).check(matches(ViewMatchers.withEffectiveVisibility(ViewMatchers.Visibility.GONE)))
Erfan Eghterafi
  • 4,344
  • 1
  • 33
  • 44
Pabel
  • 652
  • 7
  • 15
8

If you want to check if View is either not visible or does not exist.

public static ViewAssertion isNotDisplayed() {
    return new ViewAssertion() {
        @Override
        public void check(View view, NoMatchingViewException noView) {
            if (view != null && isDisplayed().matches(view)) {
                throw new AssertionError("View is present in the hierarchy and Displayed: "
                        + HumanReadables.describe(view));
            }
        }
    };
}

Usage:

onView(withId(R.id.someView)).check(isNotDisplayed());
jimmy0251
  • 16,293
  • 10
  • 36
  • 39
  • 1
    Thanks for this - IMHO this is the best solution for a generalized "check if the view is gone from the screen". One correction, though: IME, the usage is `onView(withId(R.id.someView)).check(isNotDisplayed());` – Sterling Jun 05 '18 at 23:35