总目录:Espresso从开始到…
只要使用了Espresso,那么你一定不会对withId(R.id.xxx)
和withText(R.string.xxx)
这些ViewMatchers
感到陌生。实际上无论是ViewMatchers
、RootMatchers
亦或者是Matchers
,这些本质上都是Matcher
。只是为了方便不同的使用环境进行了封装,本文将对Matcher
以及这些封装后的工具进行分析。
Matcher
所有的matcher都实现了接口Matcher
public interface Matcher<T> extends SelfDescribing {
//遍历当前视图中的 view ,匹配则返回true,失败返回false
boolean matches(Object item);
//生成本次匹配操作的描述信息
void describeMismatch(Object item, Description mismatchDescription);
}
其中matches()
是匹配的重点所在,在这里执行匹配的操作。
但是在使用过程中,我们并没有直接实现Matcher,而是实现其子类BaseMatcher所派生的封装类:TypeSafeMatcher
和BoundedMatcher
1.TypeSafeMatcher
TypeSafeMatcher
封装后的最大的区别是,增加了 isInstance()
检查当前参加匹配的目标是否符合条件。我们看一下源码,为了便于区别和阅读,只筛选出来一部分代码:
public abstract class TypeSafeMatcher<T> extends BaseMatcher<T> {
final private Class<?> expectedType;
protected TypeSafeMatcher(Class<?> expectedType) {
this.expectedType = expectedType;
}
protected abstract boolean matchesSafely(T item);
public final boolean matches(Object item) {
return item != null
&& expectedType.isInstance(item)
&& matchesSafely((T) item);
}
final public void describeMismatch(Object item, Description description) {
......
}
}
这里我们可以清楚的看出和原始的BaseMatcher
最大的区别是存储了一个expectedType
,在matchesSafely()
判断前会增加一个判断,当前 item是否是expectedType
的实例或者子类。这样可以防止出现不同类型的恰好匹配的情况,相对于BaseMatcher
是更加安全的。
我们看一个具体使用的栗子:
public static Matcher<View> withId(final int id) {
return new TypeSafeMatcher<View>() {
......
@Override
public void describeTo(Description description) {