I have a RecyclerView (R.id.recyclerView) where each row has an image (R.id.row_image) and a TextView. I want to click on the image in the first row.
I've tried to use onData(..) but it doesn't seem to work.
10 Answers
onView(withId(R.id.recyclerView))
.perform(actionOnItemAtPosition(0, click()));
Include this in your gradle script:
dependencies {
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.0'
}
-
1I get Test running failed: Instrumentation run failed due to 'java.lang.ClassNotFoundException' when I add espresso-contrib. – dannyroa Mar 23 '15 at 21:01
-
@dannyroa, you should exclude group: 'javax.inject' on it – midnight Apr 13 '15 at 13:14
-
3so, how do you `check(isDisplayed())` ? – Christopher Francisco Feb 03 '16 at 19:24
-
for folks having @dannyroa's issue, check out jdebon's answer below – Gabor Feb 03 '16 at 20:31
-
New AndroidX dependencies are described here https://developer.android.com/training/testing/set-up-project – Michael Osofsky Jan 30 '19 at 21:34
-
the dependence androidTestCompile 'com.android.support.test:testing-support-lib:0.1' is not required to perform a click in a RV, that can cause problem to compile Kotlin Code. – Ângelo Polotto Apr 26 '19 at 17:55
-
https://developer.android.com/training/testing/espresso/lists#recycler-view-list-items refer here for more details – Anmol Oct 13 '19 at 10:37
Just to add to Gabor's answer (which is the correct and complete answer since Espresso 2.0).
You may encounter problems at the moment when using espresso-contrib
and RecyclerView
s (see android-test-kit ticket).
A workaround is to add this exclusion in the espresso-contrib
dependency Gabor mentioned above:
androidTestCompile('com.android.support.test.espresso:espresso-contrib:2.0') {
exclude group: 'com.android.support', module: 'appcompat'
exclude group: 'com.android.support', module: 'support-v4'
exclude module: 'recyclerview-v7'
}
(This is an answer instead of a comment to Gabor's answer because I don't have the right to post comments yet)

- 1,753
- 1
- 13
- 24
Edit:
Espresso 2.0 has been released, the changelog includes the following:
New Features
- espresso-contrib
- RecyclerViewActions: handles interactions with RecyclerViews
Old Answer
I haven't yet tested this myself, but Thomas Keller posted this on G+ with a short explanation and a link to a Gist with the necessary view matchers.
Since the new
RecyclerView
API inherits fromViewGroup
and not fromAdapterView
, you cannot use Espresso'sonData()
to test layouts using this component.
I'll attach the code, just for completeness sake (note: not mine! All credit goes to Thomas Keller)
ViewMatcher:
public class ViewMatchers {
@SuppressWarnings("unchecked")
public static Matcher<View> withRecyclerView(@IdRes int viewId) {
return allOf(isAssignableFrom(RecyclerView.class), withId(viewId));
}
@SuppressWarnings("unchecked")
public static ViewInteraction onRecyclerItemView(@IdRes int identifyingView, Matcher<View> identifyingMatcher, Matcher<View> childMatcher) {
Matcher<View> itemView = allOf(withParent(withRecyclerView(R.id.start_grid)),
withChild(allOf(withId(identifyingView), identifyingMatcher)));
return Espresso.onView(allOf(isDescendantOfA(itemView), childMatcher));
}
}
And sample usage:
onRecyclerItemView(R.id.item_title, withText("Test"), withId(R.id.item_content))
.matches(check(withText("Test Content")));
You should use a Custom ViewAction:
public void clickOnImageViewAtRow(int position) {
onView(withId(R.id.recycler_view)).perform(RecyclerViewActions.actionOnItemAtPosition(position, new ClickOnImageView()));
}
public class ClickOnImageView implements ViewAction{
ViewAction click = click();
@Override
public Matcher<View> getConstraints() {
return click.getConstraints();
}
@Override
public String getDescription() {
return " click on custom image view";
}
@Override
public void perform(UiController uiController, View view) {
click.perform(uiController, view.findViewById(R.id.imageView));
}
}

- 2,808
- 1
- 16
- 17
Same answer like above but when some small modification since you have to provide the Viewholder type
With using RecyclerViewActions
fun tapOnRecyclerView(@IdRes resId: Int , position: Int) = onView(withId(resId))
.perform(actionOnItemAtPosition<RecyclerView.ViewHolder>(position, click()));
and to include this libraries in your project , use this
androidTestImplementation "androidx.test.espresso:espresso-core:$espressoVersion"
androidTestImplementation "androidx.test.espresso:espresso-contrib:$espressoVersion"
Prefer to use the latest espresso version from this link

- 277
- 3
- 13
I have found two ways:
- Assuming you have a textview with id "R.id.description" for each item in the RecyclerView. You can do this to match a specific child:
onView(allOf(withId(R.id.place_description),withText("what"))).perform(click());
- A tutorial from Android Testing Codelab https://codelabs.developers.google.com/codelabs/android-testing/#0
`
public Matcher<View> withItemText(final String itemText) {
checkArgument(!TextUtils.isEmpty(itemText),"cannot be null");
return new TypeSafeMatcher<View>() {
@Override
protected boolean matchesSafely(View item) {
return allOf(isDescendantOfA(isAssignableFrom(RecyclerView.class)),withText(itemText)).matches(item);
}
@Override
public void describeTo(Description description) {
description.appendText("is descendant of a RecyclerView with text" + itemText);
}
};
}
`
And then, do this:
onView(withItemText("what")).perform(click());

- 54,294
- 25
- 151
- 185

- 141
- 1
- 3
-
The first way is the best for me, because it doen't require espresso-contrib, that broke my applications' build. – Artem Mostyaev Mar 30 '16 at 05:46
You needn't to add "testing-support-lib", neither "espresso:espresso-core". They are transitive added when "espresso:espresso-contrib" is added.
build.grade
dependencies {
androidTestCompile 'com.android.support.test:runner:0.3'
androidTestCompile 'com.android.support.test:rules:0.3'
androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.2'
}
Usage:
onView(withId(R.id.recyclerView)).perform(
RecyclerViewActions.actionOnItemAtPosition(0, click()));

- 8,093
- 5
- 43
- 71
I followed @Gabor's answer but when I included the libraries, I hit the dex limit!
So, I removed the libraries, added this getInstrumentation().waitForIdleSync();
and then just called onView(withId...))...
Works perfectly.
In your case you will have multiple image views with the same ID so you will have to figure out something on how you can select the particular list item.

- 18,146
- 4
- 66
- 89
As I posted here you can implement your custom RecyclerView
matcher. Let's assume you have RecyclerView
where each element has subject you wonna match:
public static Matcher<RecyclerView.ViewHolder> withItemSubject(final String subject) {
Checks.checkNotNull(subject);
return new BoundedMatcher<RecyclerView.ViewHolder, MyCustomViewHolder>(
MyCustomViewHolder.class) {
@Override
protected boolean matchesSafely(MyCustomViewHolder viewHolder) {
TextView subjectTextView = (TextView)viewHolder.itemView.findViewById(R.id.subject_text_view_id);
return ((subject.equals(subjectTextView.getText().toString())
&& (subjectTextView.getVisibility() == View.VISIBLE)));
}
@Override
public void describeTo(Description description) {
description.appendText("item with subject: " + subject);
}
};
}
And usage:
onView(withId(R.id.my_recycler_view_id)
.perform(RecyclerViewActions.actionOnHolderItem(withItemSubject("My subject"), click()));
Basically you can match anything you want. In this example we used subject TextView
but it can be any element inside the RecyclerView
item.
One more thing to clarify is check for visibility (subjectTextView.getVisibility() == View.VISIBLE)
. We need to have it because sometimes other views inside RecyclerView
can have the same subject but it would be with View.GONE
. This way we avoid multiple matches of our custom matcher and target only item that actually displays our subject.
With this code, you can scroll the recycler view to find your item withText and perform click or other action on it.
dependencies
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.3.0'
Code
@Test
public void scrollRecyclerViewAndClick() {
onView(withId(R.id.recycler_view)).
perform(RecyclerViewActions.
actionOnItem(withText("specific string"), click()));
}

- 1,728
- 5
- 26
- 42

- 94
- 6