Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android Espresso onData with doesNotExist

I am trying to verify that a ListView does not contain a particular item. Here's the code I'm using:

onData(allOf(is(instanceOf(Contact.class)), is(withContactItemName(is("TestName")))))
      .check(doesNotExist());

When the name exists, I correctly get an error because of check(doesNotExist()). When the name does not exist, I get the following error, because allOf(...) doesn't match anything:

Caused by: java.lang.RuntimeException: No data found matching: 
(is an instance of layer.sdk.contacts.Contact and is with contact item name:
is "TestName")

How can I get functionality like onData(...).check(doesNotExist())?

EDIT:

I have a terrible hack to get the functionality I'd like by using try/catch and inspecting the event's getCause(). I would love to replace this with a good technique.

like image 668
sjones Avatar asked Jan 16 '14 21:01

sjones


1 Answers

According to Espresso samples you must not use onData(...) to check if view doesn't exists in adapter. Check this out - link. Read "Asserting that a data item is not in an adapter" part. You have to use a matcher together with onView() that finds the AdapterView.

Based on Espresso samples from link above:

  1. matcher:

     private static Matcher<View> withAdaptedData(final Matcher<Object> dataMatcher) {
         return new TypeSafeMatcher<View>() {
    
             @Override
             public void describeTo(Description description) {
                 description.appendText("with class name: ");
                 dataMatcher.describeTo(description);
             }
    
             @Override
             public boolean matchesSafely(View view) {
                 if (!(view instanceof AdapterView)) {
                     return false;
                 }
    
                 @SuppressWarnings("rawtypes")
                 Adapter adapter = ((AdapterView) view).getAdapter();
                 for (int i = 0; i < adapter.getCount(); i++) {
                     if (dataMatcher.matches(adapter.getItem(i))) {
                         return true;
                     }
                 }
                 return false;
             }
         };
     }
    
  2. then onView(...), where R.id.list is the id of your adapter ListView:

     @SuppressWarnings("unchecked")
     public void testDataItemNotInAdapter(){
         onView(withId(R.id.list))
             .check(matches(not(withAdaptedData(is(withContactItemName("TestName"))))));
     }
    

And one more suggestion - to avoid writing is(withContactItemName(is("TestName")) add below code to your matcher:

    public static Matcher<Object> withContactItemName(String itemText) {
        checkArgument( itemText != null );
        return withContactItemName(equalTo(itemText));
    }

then you'll have more readable and clear code is(withContactItemName("TestName")

like image 85
denys Avatar answered Nov 15 '22 06:11

denys