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.
问题:
回答1:
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()));
回答2:
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 { @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 isToast() { return new ToastMatcher(); }
This works like a charm for me.
回答3:
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 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.
回答4:
First create a cutom Toast Matcher which we can use in our test cases -
public class ToastMatcher extends TypeSafeMatcher { @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 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.
回答5:
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 withDuration(int) // create a matcher that calls getView() and applies the given view matcher Matcher withView(Matcher viewMatcher) another answer regarding this if(someToast == null) someToast = Toast.makeText(this, "sdfdsf", Toast.LENGTH_LONG); boolean isShown = someToast.getView().isShown();