NoMatchingRootException Espresso与自定义Toast

时间:2015-11-27 16:55:36

标签: android testing android-espresso

我开始使用Espresso,并且当用户输入错误时我会显示自定义吐司(我知道我可以使用EditText.setError(),但是那个' s就是这样)。

这是Toast的代码

 private static void showToast(Context context, String message, boolean isError) {
        if (context != null) {
            LayoutInflater inflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
            TextView toastView = (TextView) inflater.inflate(R.layout.error_toast_layout, null);
            if (!isError) {
                toastView.setBackgroundColor(context.getResources().getColor(R.color.alert_positive));
            }
            toastView.setText(message);
            Toast errorToast = new Toast(context);
            errorToast.setGravity(Gravity.TOP, 0, 0);
            errorToast.setDuration(Toast.LENGTH_SHORT);
            errorToast.setView(toastView);
            errorToast.show();
        }
    }

我正在写一个小小的UI测试,断言当用户输入错误的输入时会显示正确的Toasts

这是测试

   @RunWith(AndroidJUnit4.class)
    @LargeTest
    public class ForgotPasswordTest extends BaseEspressoTest<ForgotPasswordActivity> {

        @Test
        public void testEmailNotEntered() {
            onView(withId(R.id.email_et)).perform(typeText("w"), closeSoftKeyboard());
            onView(withId(R.id.btn_submit)).perform(click());
            onView(withText(R.string.incorrect_email_dialog)).inRoot(withDecorView(not(mActivityRule.getActivity().getWindow().getDecorView()))).check(matches(isDisplayed()));     
    }
}

如果我将自定义Toast替换为常规Toast,这可以正常工作,但是当我尝试使用它时失败。我可以看到在测试过程中正在显示Toast。

这是错误:

  

android.support.test.espresso.NoMatchingRootException:Matcher&#39; with   装饰视图不是   &#39;不匹配以下任何一项   根源:   [Root{application-window-token=android.view.ViewRootImpl$W@2d629b84,   window-token=android.view.ViewRootImpl$W@2d629b84,   has-window-focus = true,layout-params-type = 1,   layout-params-string = WM.LayoutParams {(0,0)(fillxfill)sim =#22 ty = 1   fl =#8d810100 pfl = 0x8 wanim = 0x1030461 surfaceInsets = Rect(0,0 - 0,0)},   decor-view-string = DecorView {id = -1,visibility = VISIBLE,width = 1080,   height = 1920,has-focus = true,has-focusable = true,   has-window-focus = true,is-clickable = false,is-enabled = true,   is-focused = false,is-focusable = false,is-layout-requested = false,   is-selected = false,root-is-layout-requested = false,   has-input-connection = false,x = 0.0,y = 0.0,child-count = 1}}]

我也试图根据它应该关注的事实来匹配Toast:

onView(withText(R.string.incorrect_email_dialog)).inRoot(isFocusable()).check(matches(isDisplayed()));

但这只是说它无法在视图层次结构中找到它:

  

找不到层次结构中的视图匹配:来自资源ID的字符串:   &lt; 2131165635&gt; [incorrect_email_dialog]值:请输入有效的电子邮件

1 个答案:

答案 0 :(得分:1)

您可以尝试使用下面给出的CustomToastMatcher:

500 Internal Server Error

在测试用例中使用它:

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) {
                  //means this window isn't contained by any other windows. 
                }
            }
            return false;
        }
    }

其他参考文献: https://stackoverflow.com/a/33387980/2069407 http://baroqueworksdev.blogspot.de/2015/03/how-to-check-toast-window-on-android.html