Espresso - Check RecyclerView items are ordered correctly

后端 未结 5 2066
一个人的身影
一个人的身影 2021-01-05 03:18

How to go about checking whether RecyclerView items are displayed in the correct order using Espresso? I\'m trying to test it checking it by the text for the title of each e

5条回答
  •  星月不相逢
    2021-01-05 03:56

    As it's been mentioned here, RecyclerView objects work differently than AdapterView objects, so onData() cannot be used to interact with them.

    In order to find a view at specific position of a RecyclerView you need to implement a custom RecyclerViewMatcher like below:

    public class RecyclerViewMatcher {
        private final int recyclerViewId;
    
        public RecyclerViewMatcher(int recyclerViewId) {
            this.recyclerViewId = recyclerViewId;
        }
    
        public Matcher atPosition(final int position) {
            return atPositionOnView(position, -1);
        }
    
        public Matcher atPositionOnView(final int position, final int targetViewId) {
    
            return new TypeSafeMatcher() {
                Resources resources = null;
                View childView;
    
                public void describeTo(Description description) {
                    String idDescription = Integer.toString(recyclerViewId);
                    if (this.resources != null) {
                        try {
                            idDescription = this.resources.getResourceName(recyclerViewId);
                        } catch (Resources.NotFoundException var4) {
                            idDescription = String.format("%s (resource name not found)",
                                                          new Object[] { Integer.valueOf
                                                              (recyclerViewId) });
                        }
                    }
    
                    description.appendText("with id: " + idDescription);
                }
    
                public boolean matchesSafely(View view) {
    
                    this.resources = view.getResources();
    
                    if (childView == null) {
                        RecyclerView recyclerView =
                            (RecyclerView) view.getRootView().findViewById(recyclerViewId);
                        if (recyclerView != null && recyclerView.getId() == recyclerViewId) {
                            childView = recyclerView.findViewHolderForAdapterPosition(position).itemView;
                        }
                        else {
                            return false;
                        }
                    }
    
                    if (targetViewId == -1) {
                        return view == childView;
                    } else {
                        View targetView = childView.findViewById(targetViewId);
                        return view == targetView;
                    }
    
                }
            };
        }
    }
    

    And then use it in your test case in this way:

    @Test
    void testCase() {
        onView(new RecyclerViewMatcher(R.id.rv_metrics)
            .atPositionOnView(0, R.id.txt_title))
            .check(matches(withText("Weight")))
            .perform(click());
    
        onView(new RecyclerViewMatcher(R.id.rv_metrics)
            .atPositionOnView(1, R.id.txt_title))
            .check(matches(withText("Height")))
            .perform(click());
    }
    

提交回复
热议问题