BottomNavigationItemView
实现了具有ItemView
方法的setChecked()
接口。
我试图用Espresso断言我检查了一个itemView但是我得到了同样的错误,无论我的期望值是什么,isChecked()
还是isNotChecked()
。
我的测试:
ViewInteraction buttonHome = onView(
allOf(withId(R.id.bottomHome),
childAtPosition(
childAtPosition(
withId(R.id.bottom_navigation),
0),
0),
isDisplayed()));
buttonHome.check(matches(isNotChecked()));
错误消息
android.support.test.espresso.base.DefaultFailureHandler$AssertionFailedWithCauseError: 'with checkbox state: is <true>' doesn't match the selected view.
Expected: with checkbox state: is <true>
Got: "BottomNavigationItemView{id=2131493015, res-name=bottomHome, visibility=VISIBLE, width=360, height=168, has-focus=false, has-focusable=false, has-window-focus=true, is-clickable=true, 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=2}"
如何断言BottomNavigationItemView
是BottomNavigationView
的当前所选项?
答案 0 :(得分:3)
isChecked()
和isNotChecked()
期望Checkable接口由视图实现。
此外,BottomNavigationItemView
会在itemData
字段内隐藏其已检查状态。这意味着开箱即用的Espresso不支持这种检查。幸运的是,Espresso是一个非常易扩展的框架,您可以轻松地为其添加功能。在这种情况下,我们需要编写一个自定义匹配器来进行检查。
所述匹配器的实现可能如下所示:
public static Matcher<View> withBottomNavItemCheckedStatus(final boolean isChecked) {
return new BoundedMatcher<View, BottomNavigationItemView>(BottomNavigationItemView.class) {
boolean triedMatching;
@Override
public void describeTo(Description description) {
if (triedMatching) {
description.appendText("with BottomNavigationItem check status: " + String.valueOf(isChecked));
description.appendText("But was: " + String.valueOf(!isChecked));
}
}
@Override
protected boolean matchesSafely(BottomNavigationItemView item) {
triedMatching = true;
return item.getItemData().isChecked() == isChecked;
}
};
}
用法是:
buttonHome.check(matches(withBottomNavItemCheckedStatus(false)));
答案 1 :(得分:1)
Based on the above answer and comments, I created this matcher:
import android.support.design.widget.BottomNavigationView;
import android.support.test.espresso.matcher.BoundedMatcher;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import java.util.HashSet;
import java.util.Set;
import org.hamcrest.Description;
import org.hamcrest.Matcher;
/**
* Custom matchers for Espresso.
*/
public class EspressoUtils {
/**
* Checks that {@link BottomNavigationView} contains an item with provided id and that it is
* checked.
*
* @param id of the item to find in the navigation view
* @return a matcher that returns true if the item was found and checked
*/
public static Matcher<View> hasCheckedItem(final int id) {
return new BoundedMatcher<View, BottomNavigationView>(BottomNavigationView.class) {
Set<Integer> checkedIds = new HashSet<>();
boolean itemFound = false;
boolean triedMatching = false;
@Override public void describeTo(Description description) {
if (!triedMatching) {
description.appendText("BottomNavigationView");
return;
}
description.appendText("BottomNavigationView to have a checked item with id=");
description.appendValue(id);
if (itemFound) {
description.appendText(", but selection was=");
description.appendValue(checkedIds);
} else {
description.appendText(", but it doesn't have an item with such id");
}
}
@Override protected boolean matchesSafely(BottomNavigationView navigationView) {
triedMatching = true;
final Menu menu = navigationView.getMenu();
for (int i = 0; i < menu.size(); i++) {
final MenuItem item = menu.getItem(i);
if (item.isChecked()) {
checkedIds.add(item.getItemId());
}
if (item.getItemId() == id) {
itemFound = true;
}
}
return checkedIds.contains(id);
}
};
}
}
That can be used like:
@Test public void verifyWalletIsSelected() throws Exception {
onView(withId(R.id.navigation)).check(matches(hasCheckedItem(R.id.navigation_wallet)));
}