Encountering the AmbigousViewMatcherException means that your code does not know which UI element needs to invoke a certain action. The reason is that there are multiple elements in the current screen that has the same ViewMatcher inside your onView() function.

Consider the following UI mockup above that has similar resource id to it's start button (the only difference is that the other buttons are disabled). If you use the below snippet it will return an AmbigousViewMatcherException because it doesn't know which start button to click. Quick fix to this is to update each of the button with similar resource ids unique. But what if it's not possible because the cost benefit of updating the code is not worth it?

Espresso.onView(withId(R.id.startButton)).perform(ViewActions.click())

So how do I click the Blue Button?

In my previous article I explained the basics on how to use ViewMatchers and promised to do a follow up on how to effectively use it on complex scenarios. One of the things that I mentioned is that you can chain multiple ViewMatchers. Maybe, chain is not the right term, but you can use multiple ViewMatchers inside onView() with the help of Hamcrest Matchers, specifically the allOf() function.

For simple unique views you can use the onView() function like this. The code simply looks for an android view with a resource id of startButton.

Espresso.onView(withId(R.id.startButton)).perform(ViewActions.click())

But if there are two UI elements  sharing the same resource id and you use the code above it will then return  the AmbigousViewMatcherException. What you need to do is to use the allOf Hamcrest Matcher inside the onView() and then pass the ViewMatchers that you need inside the  allOf() function, so it will look something like this.

import org.hamcrest.Matchers.allOf

val multipleSelectors = allOf(withId(R.id.startButton), isEnabled())
Espresso.onView(multipleSelectors).perform(ViewActions.click())

or like this...

import org.hamcrest.Matchers.allOf

Espresso.onView(
	allOf(
    	withId(R.id.startButton),
        isEnabled()
    )
).perform(ViewActions.click())

Note that you need to import the hamcrest matcher as it's not part of the Espresso Library. Simply put the allOf() function serves as an AND operand for ViewMatchers. It's like saying

Find an element with all of these attributes on the screen and then perform this action

When I was learning Espresso for the first time, I was kinda new to Hamcrest Matchers and reading the onView in conjuction of allOf threw me off. I was reading it to something like this. "Find all of the elements with these attributes and perform this action" which is technically not the case!

Fixing AmbigousViewMatcherException doesn't end here

Nope! it doesn't end here because there are cases where Android UI elements are completely identical! So how do we tell our code to perform a click to the element that we truly want? Find out on the Part 2 of of How to fix AmbigousViewMatcherException on my upcoming article.