我有一个在RecyclerView中使用的具有垂直LinearLayout Manager的列表项。我正在使用espresso,我想模拟单击id / action_save菜单项。以下是我最近尝试解决这个问题的尝试。我尝试过将onData方法与onChildView结合使用,但是MenuItem不是View。如果菜单项位于操作栏中的工具栏中,但嵌入在RecyclerView中,则onView和withId方法可以正常工作。
我尝试使用android studio中的espresso录制功能进行录制,但是,它会注入类似于Espresso click menu item的代码。再次运行测试用例会导致测试引发异常。
<android.support.v7.widget.CardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:cardCornerRadius="0dp"
app:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<android.support.v7.widget.Toolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="@color/colorPrimaryDark"
android:elevation="4dp"
android:minHeight="?attr/actionBarSize"
app:popupTheme="@style/MyDarkToolbarStyle"
app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" />
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1">
<ProgressBar
android:id="@+id/progress"
style="@style/Widget.AppCompat.ProgressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:indeterminate="true" />
<android.support.v7.widget.AppCompatImageView
android:id="@+id/imgPalette"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:minHeight="250dp" />
</RelativeLayout>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:layout_marginTop="-2dp"
android:elevation="4dp"
android:outlineProvider="bounds"
android:paddingTop="2dp">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/colorPrimaryDark">
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
</FrameLayout>
</FrameLayout>
</LinearLayout>
</android.support.v7.widget.CardView>
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/action_save"
android:title="@string/save"
app:showAsAction="never" />
</menu>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="match_parent">
...
<android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/banner" />
...
</RelativeLayout>
...
// mProducts is a list that is backed by the adapter and is of Type Product
for (int i = 0; i < mProducts.size(); i++) {
onView(allOf(withId(R.id.recyclerView), withParent(withId(R.id.container))))
.perform(actionOnItemAtPosition(i, clickOverflow(R.id.toolbar)));
// Add delay for system to respond to overflow being opened
SystemClock.sleep(1000);
onView(withId(R.id.recyclerView)).perform(actionOnItemAtPosition(i, clickMenuItem(R.id.toolbar, R.id.action_save)));
}
...
public static ViewAction clickMenuItem(final int toolbarId, final int id) {
return new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return null;
}
@Override
public String getDescription() {
return "Click on a child view with specified id.";
}
@Override
public void perform(UiController uiController, View view) {
Toolbar toolbar = (Toolbar) view.findViewById(toolbarId);
for (int i = 0; i < toolbar.getChildCount(); i++) {
if (toolbar.getChildAt(i) instanceof ActionMenuView) {
ViewGroup viewGroup = ((ViewGroup) toolbar.getChildAt(i));
for (int j = 0; j < viewGroup.getChildCount(); j++) {
if (viewGroup.getChildAt(j).getId() == id) {
viewGroup.getChildAt(j).performClick();
break;
}
}
}
}
}
};
}
public static ViewAction clickOverflow(final int toolbarId) {
return new ViewAction() {
@Override
public Matcher<View> getConstraints() {
return null;
}
@Override
public String getDescription() {
return "Click on a child view with specified id.";
}
@Override
public void perform(UiController uiController, View view) {
Toolbar toolbar = (Toolbar) view.findViewById(toolbarId);
((ViewGroup) toolbar.getChildAt(0)).getChildAt(0).performClick();
}
};
}
android.support.test.espresso.NoMatchingViewException: No views in hierarchy found matching: with id: com.variable.inspire:id/recyclerView
If the target view is not part of the view hierarchy, you may need to use Espresso.onData to load it from one of the following AdapterViews:android.support.v7.widget.MenuPopupWindow$MenuDropDownListView{92d26ac VFED.VC.. .F...... 0,0-515,252}
这不能解决我的问题,但通过直接显示菜单项而不是溢出菜单中提供了一种解决方法。我的问题仍然是使用浓缩咖啡,你可以打开溢出菜单并单击其中的项目。
onView(allOf(withId(R.id.recyclerView), withParent(withId(R.id.container)))).perform(actionOnItemAtPosition(i, clickMenuItem(R.id.toolbar, R.id.action_save)));