It is required to catch the case when the toast does not exist, for which NoMatchingRootException . The following is the Espresso method for this.
public static Matcher<Root> isToast() { return new WindowManagerLayoutParamTypeMatcher("is toast", WindowManager.LayoutParams.TYPE_TOAST); } public static void assertNoToastIsDisplayed() { onView(isRoot()) .inRoot(isToast()) .withFailureHandler(new PassMissingRoot()) .check(matches(not(anything("toast root existed")))) ; }
A quick (self-diagnostic) test that uses the following:
@Test public void testToastMessage() { Toast toast = createToast("Hello Toast!"); assertNoToastIsDisplayed(); toast.show(); onView(withId(android.R.id.message)) .inRoot(isToast()) .check(matches(withText(containsStringIgnoringCase("hello")))); toast.cancel(); assertNoToastIsDisplayed(); } private Toast createToast(final String message) { final AtomicReference<Toast> toast = new AtomicReference<>(); InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() { @SuppressLint("ShowToast")
Reuse magic classes:
public class PassMissingRoot implements FailureHandler { private final FailureHandler defaultHandler = new DefaultFailureHandler(InstrumentationRegistry.getTargetContext()); @Override public void handle(Throwable error, Matcher<View> viewMatcher) { if (!(error instanceof NoMatchingRootException)) { defaultHandler.handle(error, viewMatcher); } } } public class WindowManagerLayoutParamTypeMatcher extends TypeSafeMatcher<Root> { private final String description; private final int type; private final boolean expectedWindowTokenMatch; public WindowManagerLayoutParamTypeMatcher(String description, int type) { this(description, type, true); } public WindowManagerLayoutParamTypeMatcher(String description, int type, boolean expectedWindowTokenMatch) { this.description = description; this.type = type; this.expectedWindowTokenMatch = expectedWindowTokenMatch; } @Override public void describeTo(Description description) { description.appendText(this.description); } @Override public boolean matchesSafely(Root root) { if (type == root.getWindowLayoutParams().get().type) { IBinder windowToken = root.getDecorView().getWindowToken(); IBinder appToken = root.getDecorView().getApplicationWindowToken(); if (windowToken == appToken == expectedWindowTokenMatch) {
source share