Would anyone know how to test for the appearance of a Toast message in android espresso? In robotium its easy & I used but started working in espresso but dont getting the exact command.
-
3Any of the following solution won't work if the activity is being finished at the same time as the toast is displayed. – Slav Dec 01 '17 at 09:47
-
@Slav did you find any solution that will include Toast checking even in the case when Activity is finished? – NixSam Dec 05 '18 at 10:14
-
@NixSam Unfortunately not. If I remember correctly, in case of finishing Activity, I settled on checking that the Activity is being finished. – Slav Dec 05 '18 at 10:56
-
@Slav thanks for the info – NixSam Dec 05 '18 at 14:32
14 Answers
This slightly long statement works for me:
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.is;
import static org.hamcrest.Matchers.not;
....
onView(withText(R.string.TOAST_STRING)).inRoot(withDecorView(not(is(getActivity().getWindow().getDecorView())))).check(matches(isDisplayed()));

- 1,524
- 1
- 9
- 8
-
8
-
7@Slava is correct, it can be done by removing is: onView(withText(R.string.TOAST_STRING)).inRoot(withDecorView(not(getActivity().getWindow().getDecorView()))) .check(matches(isDisplayed())); – bond Apr 20 '15 at 18:03
-
6
-
8@John: You’re probably using the new [JUnit rule-based tests](https://code.google.com/p/android-test-kit/wiki/JUnit4RulesInATSL) with an `ActivityTestRule`. You can get the activity from that rule using [`ActivityTestRule#getActivity()`](https://android-test-kit.googlecode.com/git/docs/android-support-test-javadocs-0.2/reference/android/support/test/rule/ActivityTestRule.html#getActivity()). – Leo Nikkilä Aug 29 '15 at 18:20
-
26With ActivityTestRule: `onView(withText(R.string.toast_text)).inRoot(withDecorView(not(mActivityRule.getActivity().getWindow().getDecorView()))).check(matches(isDisplayed()));` – StefanTo Dec 08 '15 at 14:29
-
1This works on a flat layout, but failed on AlertDialog. I had use custom this https://stackoverflow.com/a/33387980/2069407 answer for toast msg on AlertDialog. – s-hunter Nov 19 '17 at 04:07
-
what if I don't know the toast message, consider a case like the toast is a network API error message then how can I detect the toast – MarGin Mar 28 '19 at 12:11
-
This doesn't work's for dialog's but this does https://stackoverflow.com/a/33387980/7972699 – Anmol Oct 13 '19 at 18:35
-
2I am using ActivityScenario.launch(MainActivity::class.java) to launch my activity. How do i get "getActivity()" ? – Mervin Hemaraju Jun 23 '20 at 11:16
-
1
-
2Is anybody else having trouble with testing toast on Android 11? I just can't make it work. But it works flawlesly on lower version. – Brontes Mar 30 '21 at 06:24
-
@Brontes Can confirm. Failed with error message: "androidx.test.espresso.NoMatchingRootException: Matcher 'with decor view not is". – rabyunghwa May 21 '21 at 09:55
-
3@Brontes: Just a note: This approach (and most other answers) does not work on Android 11 API 30, when using `"targetSdkVersion 30"` and `"compileSdkVersion 30"`. See: https://github.com/android/android-test/issues/803 – Mr-IDE Sep 08 '21 at 15:33
The accepted answer is a good one but didn't work for me. So I searched a bit and found this blog article. This gave me an idea of how to do it and I updated the solution above.
First I implemented the ToastMatcher:
import android.os.IBinder;
import android.support.test.espresso.Root;
import android.view.WindowManager;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
public class ToastMatcher extends TypeSafeMatcher<Root> {
@Override
public void describeTo(Description description) {
description.appendText("is toast");
}
@Override
public boolean matchesSafely(Root root) {
int type = root.getWindowLayoutParams().get().type;
if (type == WindowManager.LayoutParams.TYPE_TOAST) {
IBinder windowToken = root.getDecorView().getWindowToken();
IBinder appToken = root.getDecorView().getApplicationWindowToken();
if (windowToken == appToken) {
// windowToken == appToken means this window isn't contained by any other windows.
// if it was a window for an activity, it would have TYPE_BASE_APPLICATION.
return true;
}
}
return false;
}
}
Then I implemented my check methods like this:
public void isToastMessageDisplayed(int textId) {
onView(withText(textId)).inRoot(MobileViewMatchers.isToast()).check(matches(isDisplayed()));
}
MobileViewMatchers is a container for accessing the matchers. There I defined the static method isToast()
.
public static Matcher<Root> isToast() {
return new ToastMatcher();
}
This works like a charm for me.

- 7,988
- 3
- 30
- 39
-
2This isn't working for me, as the test continuously loops. The only thing that works is if I touch the screen while the toast is open it appears to stop idling and will then work. Any ideas? – AdamMc331 Sep 06 '16 at 18:16
-
I need to know your test setup. What do you want to test and what is displayed? Sounds like a progress issue, http://stackoverflow.com/questions/33289152/progressbars-and-espresso/36201647#36201647. Does this happen on all API versions? – Thomas R. Sep 07 '16 at 06:36
-
I haven't tested multiple API versions. What happens is we are making an API call when a fragment loads, which is mocking a failure response, in which case all we do is show the toast. I can try to make a gist of what I'm doing later on today. – AdamMc331 Sep 07 '16 at 15:58
-
2Where does "MobileViewMatchers" come from? It cant be imported or found in the code – HRVHackers Sep 22 '16 at 22:05
-
The method isToast() is defined in that class. With the code above you can use it directly without MobileViewMatchers. – Thomas R. Sep 23 '16 at 06:19
-
What do you do if you don't have a textID? The rest of your code retrieves the message correctly, but since I cant match it to the proper view I get an error message – Frikster Dec 02 '16 at 14:40
-
This works, but testing a Toast is risky as you have to wait for the correct time for it to show up. I was thinking whether it is possible to test a Toast using UiAutomator ? – Akshay Mahajan Feb 10 '17 at 09:47
-
2
-
2I am able to validate toast messages with this code only if toast appears on screen. But if there is a condition with following results : a) msg1 b)msg2 c) No toast at all. Then options a and b are validated but code get stuck in option c. What can be a possible solution for the same ? – Inderdeep Singh Feb 12 '18 at 06:18
-
Probably no longer of interest @AdamMc331 but I fixed the endless-loop-issue in my Kotlin version of the code. – yasd Apr 14 '18 at 18:23
-
@makovkastar: My Kotlin version addresses the deprecated-issue, too, to be honest by ignoring it. But toasts just seem to be of this deprecated type - at least on API level 27 (in emulator). – yasd Apr 14 '18 at 18:23
-
@ThomasR. I've just added an adaption of your code in Kotlin - thanks for the inspiration. – yasd Apr 14 '18 at 18:25
-
Please note that `Root` is not part of the public API. The accepted answer above should be the preferred solution. – rabyunghwa Jul 23 '21 at 03:29
-
3This solution had worked well for me until API 30 (Android 11). Even though I can see a toast on the screen, this code doesn't catch it. I've moved away from validating toasts altogether; thankfully they're not critical for my application. – Michael Osofsky Nov 12 '21 at 20:09
First make sure to import:
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
Inside your class you probably have a rule like this:
@Rule
public ActivityTestRule<MyNameActivity> activityTestRule =
new ActivityTestRule<>(MyNameActivity.class);
Inside your test:
MyNameActivity activity = activityTestRule.getActivity();
onView(withText(R.string.toast_text)).
inRoot(withDecorView(not(is(activity.getWindow().getDecorView())))).
check(matches(isDisplayed()));
This worked for me, and it was pretty easy to use.

- 63,191
- 45
- 217
- 228
-
4Just a note: This approach (and most other answers) do not work on Android 11 API 30, when using `"targetSdkVersion 30"` and `"compileSdkVersion 30"`. See: https://github.com/android/android-test/issues/803 – Mr-IDE Sep 08 '21 at 15:32
If you're using the newest Android Testing Tools from Jetpack, you know, that ActivityTestRule
is deprecated and you should use ActivityScenario
or ActivityScenarioRule
(which contains the first).
Prerequisites. Create decorView variable and assign it before tests;
@Rule
public ActivityScenarioRule<FeedActivity> activityScenarioRule = new ActivityScenarioRule<>(FeedActivity.class);
private View decorView;
@Before
public void setUp() {
activityScenarioRule.getScenario().onActivity(new ActivityScenario.ActivityAction<FeedActivity>() {
@Override
public void perform(FeedActivityactivity activity) {
decorView = activity.getWindow().getDecorView();
}
});
}
Test itself
@Test
public void given_when_thenShouldShowToast() {
String expectedWarning = getApplicationContext().getString(R.string.error_empty_list);
onView(withId(R.id.button))
.perform(click());
onView(withText(expectedWarning))
.inRoot(withDecorView(not(decorView)))// Here we use decorView
.check(matches(isDisplayed()));
}
getApplicationContext() can be taken from androidx.test.core.app.ApplicationProvider.getApplicationContext;

- 6,084
- 3
- 42
- 42

- 1,761
- 15
- 23
-
Thanks a lot! this worked for me, as a suggestion, you can pass the string id to `withText()` – Hermandroid Sep 02 '20 at 18:25
-
Also you can get decorView from the rule, as the other answers suggest `.inRoot(withDecorView(not(activityRule.activity.window.decorView)))` – Hermandroid Sep 02 '20 at 18:27
-
1@Herman there's no way to access a ActivityRule in this example, because we are using a `ActivityScenarioRule`. In this example, your code won't work. – Leonardo Sibela Sep 07 '20 at 16:31
-
You should really not(!) store a reference to anything from the activity during the complete test execution. Instead get the reference when you need it. Probably you struggled with the fact, that you cannot set local variables from inside a lambda. Use an AtomicReference to avoid this problem. – Aorlinn Aug 03 '21 at 13:18
First create a cutom Toast Matcher which we can use in our test cases -
public class ToastMatcher extends TypeSafeMatcher<Root> {
@Override public void describeTo(Description description) {
description.appendText("is toast");
}
@Override public boolean matchesSafely(Root root) {
int type = root.getWindowLayoutParams().get().type;
if ((type == WindowManager.LayoutParams.TYPE_TOAST)) {
IBinder windowToken = root.getDecorView().getWindowToken();
IBinder appToken = root.getDecorView().getApplicationWindowToken();
if (windowToken == appToken) {
//means this window isn't contained by any other windows.
return true;
}
}
return false;
}
}
1. Test if the Toast Message is Displayed
onView(withText(R.string.mssage)).inRoot(new ToastMatcher())
.check(matches(isDisplayed()));
2. Test if the Toast Message is not Displayed
onView(withText(R.string.mssage)).inRoot(new ToastMatcher())
.check(matches(not(isDisplayed())));
3. Test id the Toast contains specific Text Message
onView(withText(R.string.mssage)).inRoot(new ToastMatcher())
.check(matches(withText("Invalid Name"));
Thanks, Anuja
Note - this answer is from This POST.

- 80
- 5

- 1,367
- 13
- 19
-
It should be: if (windowToken == appToken) { //means this window isn't contained by any other windows. return true; } – Akshay Mahajan Feb 10 '17 at 09:55
-
@anuja jain when http://stackoverflow.com/a/40756080/5230044 answer works then why we should refer to your answer – cammando Apr 01 '17 at 17:23
-
1as noted in the original post in the comments, this does NOT work. It fails with an exception. Also this post is missing the return true; after the comment when the tokens match so it will not work either. – user330844 Sep 06 '17 at 16:14
-
-
Though the question has an accepted answer - which BTW does not work for me - I'd like to add my solution in Kotlin which I derived from Thomas R.'s answer:
package somepkg
import android.support.test.espresso.Espresso.onView
import android.support.test.espresso.Root
import android.support.test.espresso.matcher.ViewMatchers.withText
import android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
import android.view.WindowManager.LayoutParams.TYPE_TOAST
import org.hamcrest.Description
import org.hamcrest.Matcher
import org.hamcrest.TypeSafeMatcher
/**
* This class allows to match Toast messages in tests with Espresso.
*
* Idea taken from: https://stackoverflow.com/a/33387980
*
* Usage in test class:
*
* import somepkg.ToastMatcher.Companion.onToast
*
* // To assert a toast does *not* pop up:
* onToast("text").check(doesNotExist())
* onToast(textId).check(doesNotExist())
*
* // To assert a toast does pop up:
* onToast("text").check(matches(isDisplayed()))
* onToast(textId).check(matches(isDisplayed()))
*/
class ToastMatcher(private val maxFailures: Int = DEFAULT_MAX_FAILURES) : TypeSafeMatcher<Root>() {
/** Restrict number of false results from matchesSafely to avoid endless loop */
private var failures = 0
override fun describeTo(description: Description) {
description.appendText("is toast")
}
public override fun matchesSafely(root: Root): Boolean {
val type = root.windowLayoutParams.get().type
@Suppress("DEPRECATION") // TYPE_TOAST is deprecated in favor of TYPE_APPLICATION_OVERLAY
if (type == TYPE_TOAST || type == TYPE_APPLICATION_OVERLAY) {
val windowToken = root.decorView.windowToken
val appToken = root.decorView.applicationWindowToken
if (windowToken === appToken) {
// windowToken == appToken means this window isn't contained by any other windows.
// if it was a window for an activity, it would have TYPE_BASE_APPLICATION.
return true
}
}
// Method is called again if false is returned which is useful because a toast may take some time to pop up. But for
// obvious reasons an infinite wait isn't of help. So false is only returned as often as maxFailures specifies.
return (++failures >= maxFailures)
}
companion object {
/** Default for maximum number of retries to wait for the toast to pop up */
private const val DEFAULT_MAX_FAILURES = 5
fun onToast(text: String, maxRetries: Int = DEFAULT_MAX_FAILURES) = onView(withText(text)).inRoot(isToast(maxRetries))!!
fun onToast(textId: Int, maxRetries: Int = DEFAULT_MAX_FAILURES) = onView(withText(textId)).inRoot(isToast(maxRetries))!!
fun isToast(maxRetries: Int = DEFAULT_MAX_FAILURES): Matcher<Root> {
return ToastMatcher(maxRetries)
}
}
}
I hope this will be of help for later readers - the usage is described in the comment.

- 916
- 7
- 21
-
This is a really good answer and solved the problem for me because has retry policy integrated – MatPag Dec 09 '20 at 16:59
-
This works on my older devices but on android 11 it fails on two devices I've tried.. – Matt Wolfe Jun 03 '21 at 22:19
-
Thanks. And the package seems changed nowadays, it is `androidx.test.espresso.xxx` now. I mixed this with UIautomator test method together. – Zhou Haibo Feb 22 '23 at 11:57
I write my custom toast matcher:
import android.view.WindowManager
import androidx.test.espresso.Root
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
class ToastMatcher : TypeSafeMatcher<Root>() {
override fun describeTo(description: Description) {
description.appendText("is toast")
}
override fun matchesSafely(root: Root): Boolean {
val type = root.getWindowLayoutParams().get().type
if (type == WindowManager.LayoutParams.TYPE_TOAST) {
val windowToken = root.getDecorView().getWindowToken()
val appToken = root.getDecorView().getApplicationWindowToken()
if (windowToken === appToken) {
return true
}
}
return false
}
}
And use like this:
onView(withText(R.string.please_input_all_fields)).inRoot(ToastMatcher()).check(matches(isDisplayed()))

- 14,350
- 37
- 121
- 240
For kotlin, I had to use the apply extension function, and this worked for me.
1- declare your ToastMatcher class in the androidTest folder:
class ToastMatcher : TypeSafeMatcher<Root?>() {
override fun matchesSafely(item: Root?): Boolean {
val type: Int? = item?.windowLayoutParams?.get()?.type
if (type == WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW) {
val windowToken: IBinder = item.decorView.windowToken
val appToken: IBinder = item.decorView.applicationWindowToken
if (windowToken === appToken) { // means this window isn't contained by any other windows.
return true
}
}
return false
}
override fun describeTo(description: Description?) {
description?.appendText("is toast")
}
}
2- Then you use like this to test that the toast message actually displays
onView(withText(R.string.invalid_phone_number))
.inRoot(ToastMatcher().apply {
matches(isDisplayed())
});
Attribution to ToastMatcher class:
/**
* Author: http://www.qaautomated.com/2016/01/how-to-test-toast-message-using-espresso.html
*/

- 190
- 1
- 6
I would say for toast messages first define your rule
@Rule
public ActivityTestRule<AuthActivity> activityTestRule =
new ActivityTestRule<>(AuthActivity.class);
then whatever toast message text you are looking for type it in between quotation for example I used "Invalid email address"
onView(withText("Invalid email address"))
.inRoot(withDecorView(not(activityTestRule.getActivity().getWindow().getDecorView())))
.check(matches(isDisplayed()));
I would like to suggest an alternative method, especially if you need to check that particular toast is NOT displayed
The problem here that
onView(viewMatcher)
.inRoot(RootMatchers.isPlatformPopup())
.check(matches(not(isDisplayed())))
or
onView(viewMatcher)
.inRoot(RootMatchers.isPlatformPopup())
.check(doesNotExist())
or any other custom inRoot
checks
are throwing NoMatchingRootException
even before the code passes to check
method
You may just catch the exception and complete the test but that's not a good option since throwing and catching NoMatchingRootException
consumes a lot of time in a comparison with the default test case. Seems that Espresso is waiting for the Root for a while
For this case is suggest just to give up with espresso here and use UiAutomator
for this assertion. The Espresso
and UiAutomator
frameworks could easily work together in one environment.
val device: UiDevice
get() = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation())
fun assertPopupIsNotDisplayed() {
device.waitForIdle()
assertFalse(device.hasObject(By.text(yourText))))
}
fun assertPopupIsDisplayed() {
device.waitForIdle()
assertTrue(device.hasObject(By.text(yourText))))
}

- 9,723
- 7
- 40
- 71
Using ActivityScenarioRule and Java
Some imports for the code
import android.view.View;
import androidx.test.ext.junit.rules.ActivityScenarioRule;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import static androidx.test.espresso.Espresso.onView;
import static androidx.test.espresso.matcher.RootMatchers.withDecorView;
import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
import static androidx.test.espresso.matcher.ViewMatchers.withId;
import static androidx.test.espresso.matcher.ViewMatchers.withText;
import static org.hamcrest.Matchers.not;
1. Declare the rule
//Change YourActivity by the activity you are testing
@Rule
public ActivityScenarioRule<YourActivity> activityRule
= new ActivityScenarioRule<>(YourActivity.class);
2. Initialize the decor view
private View decorView;
@Before
public void loadDecorView() {
activityRule.getScenario().onActivity(
activity -> decorView = activity.getWindow().getDecorView()
);
}
3. Finally test it
@Test
public void testWithToasts() {
//Arrange and act code
//Modify toast_msg to your own string resource
onView(withText(R.string.toast_msg)).
inRoot(RootMatchers.withDecorView(not(decorView)))
.check(matches(isDisplayed()));
}

- 613
- 4
- 17
I'm pretty new to this, but I made a base class 'BaseTest' that has all of my actions (swiping, clicking, etc.) and verifications (checking text views for content, etc.).
protected fun verifyToastMessageWithText(text: String, activityTestRule: ActivityTestRule<*>) {
onView(withText(text)).inRoot(withDecorView(not(activityTestRule.activity.window.decorView))).check(matches(isDisplayed()))
}
protected fun verifyToastMessageWithStringResource(id: Int, activityTestRule: ActivityTestRule<*>) {
onView(withText(id)).inRoot(withDecorView(not(activityTestRule.activity.window.decorView))).check(matches(isDisplayed()))
}

- 105
- 1
- 2
- 8
this works for me
onView(withId(R.id.inputField)).check(matches(withText("Lalala")));

- 833
- 11
- 10
The way Toasts are implemented makes it possible to detect a toast has been displayed. However there is no way to see if a Toast has been requested, thru a call to show()) or to block between the period of time between show() and when the toast has become visible. This is opens up unresolvable timing issues (that you can only address thru sleep & hope).
If you really really want to verify this, here's a not-so-pretty alternative using Mockito and a test spy:
public interface Toaster {
public void showToast(Toast t);
private static class RealToaster {
@Override
public void showToast(Toast t) {
t.show();
}
public static Toaster makeToaster() {
return new RealToaster();
}
}
Then in your test
public void testMyThing() {
Toaster spyToaster = Mockito.spy(Toaster.makeToaster());
getActivity().setToaster(spyToaster);
onView(withId(R.button)).perform(click());
getInstrumentation().runOnMainSync(new Runnable() {
@Override
public void run() {
// must do this on the main thread because the matcher will be interrogating a view...
Mockito.verify(spyToaster).showToast(allOf(withDuration(Toast.LENGTH_SHORT), withView(withText("hello world"));
});
}
// create a matcher that calls getDuration() on the toast object
Matcher<Toast> withDuration(int)
// create a matcher that calls getView() and applies the given view matcher
Matcher<Toast> withView(Matcher<View> viewMatcher)
another answer regarding this
if(someToast == null)
someToast = Toast.makeText(this, "sdfdsf", Toast.LENGTH_LONG);
boolean isShown = someToast.getView().isShown();

- 6,417
- 3
- 40
- 58

- 411
- 4
- 10
-
11Md Hussain, don't you want to add a link in your answer to the place where you copied it - https://groups.google.com/forum/#!searchin/android-test-kit-discuss/toast/android-test-kit-discuss/uaHdXuVm-Bw/EBIGyA0Omj0J ? – denys Mar 21 '15 at 15:25
-
3Although it's true that the answer is copied, it raises a good point. The accepted answer provides a non-hermetical test, since it affects a potential following execution. – mdelolmo Jul 03 '15 at 13:07