我在Android应用程序上运行Espresso测试。测试是片状的。它可以可靠地声明数据模型已更新。我的问题是ViewMatchers无法匹配View中的相同值,因为ViewDataBinding尚未更新Views。 (至少大部分时间都是测试运行。)
当ViewDataBinding在视图上没有挂起的更改时,是否会出现IdlingResource这样的事情?
我的解决方法是调用executePendingBindings()和一个小的Thread.sleep(...)
的组合答案 0 :(得分:13)
Espresso在执行视图检查之前先进行waitForIdle
。 waitForIdle
陷入IdlingRegistry
的状态,并一直等到每个IdlingResource
都处于空闲状态。
LoopingIdlingResource
默认在Espresso中使用。它一直等待,直到循环器没有消息在队列中为止,这意味着它处于空闲状态。
然而,DataBinding
使用不同的方法来计划更新,但它使用了Choreographer.postFrameCallback
。因此,更新不会发布到循环器队列中,并且Espresso将不会等待它们。
在这种情况下,您应该注册自己的IdlingResource
。您可以在googlesamples/android-architecture-components
中找到不错的示例,了解如何实现自定义DataBindingIdlingResource
和DataBindingIdlingResourceRule
,这些自定义DataBindingIdlingResourceRule
和DataBindingIdlingResource
将在执行测试之前设置空闲资源。
因此,您必须将这些类{{3}}和{{3}}复制到测试中。
并将以下规则添加到测试类中:
@Rule
@JvmField
val dataBindingIdlingResourceRule = DataBindingIdlingResourceRule(activityRule)
答案 1 :(得分:3)
编辑:这是一个老答案。请使用Roshak的
错误报告提到使用反射将ViewDataBinding.USE_CHOREOGRAPHER
更改为false
进行测试,因此这是我提出的解决方案:
public static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField;
try {
modifiersField = Field.class.getDeclaredField("accessFlags");
} catch(NoSuchFieldException e) {
//This is an emulator JVM ¯\_(ツ)_/¯
modifiersField = Field.class.getDeclaredField("modifiers");
}
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
然后,只需为正在测试的活动定义ActivityTestRule
,并覆盖其beforeActivityLaunched()
。有必要在启动活动之前执行此操作(而不是@Before
注释),因为ViewDataBinding
如果不使用Looper
将初始化CHOREOGRAPHER
}。
@Override
protected void beforeActivityLaunched() {
super.beforeActivityLaunched();
//Because we are using data-binding, we avoid using CHOREOGRAPHER
try {
ReflectionUtils.setFinalStatic(
ViewDataBinding.class.getDeclaredField("USE_CHOREOGRAPHER"), false);
} catch (Exception e) {
Assert.fail(e.getMessage());
}
}
这样,您可以摆脱Thread.sleep()