Android 如何使Espresso等待数据绑定使用数据模型更新视图?
我正在Android应用程序上运行浓缩咖啡测试。这个测试是不可靠的。它可以可靠地断言数据模型已更新。我的问题是ViewMatchers无法匹配视图中的相同值,因为ViewDataBinding尚未更新视图。(至少在测试运行的大部分时间。) 当ViewDataBinding在视图上没有挂起的更改时,是否存在IdlingResource变为空闲的情况 我的解决方法是调用executePendingBindings()和一个小线程的组合。sleep(…)编辑:这是一个老答案。请用罗斯克的 错误报告提到使用反射来更改视图数据绑定。使用CHOREOGRAPHER将测试更改为false,因此我提出了以下解决方案:Android 如何使Espresso等待数据绑定使用数据模型更新视图?,android,android-espresso,android-testing,android-databinding,Android,Android Espresso,Android Testing,Android Databinding,我正在Android应用程序上运行浓缩咖啡测试。这个测试是不可靠的。它可以可靠地断言数据模型已更新。我的问题是ViewMatchers无法匹配视图中的相同值,因为ViewDataBinding尚未更新视图。(至少在测试运行的大部分时间。) 当ViewDataBinding在视图上没有挂起的更改时,是否存在IdlingResource变为空闲的情况 我的解决方法是调用executePendingBindings()和一个小线程的组合。sleep(…)编辑:这是一个老答案。请用罗斯克的 错误报告提到
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
,并在ActivityLaunched()之前覆盖它的。在启动活动之前必须执行此操作(与注释之前的@相反),因为视图数据绑定
将初始化活套
,如果它不使用编舞
@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());
}
}
这样,您就可以在执行视图检查之前摆脱线程waitForIdle
进入思考IdlingRegistry
并等待,直到每个IdlingSource
都处于空闲状态
默认情况下,浓缩咖啡中使用了LoopingIdlingResource
。它等待直到looper在队列中并没有消息,这意味着它是空闲的
然而,DataBinding
使用不同的方法来安排更新,它使用Choreographer.postFrameCallback
。所以更新不会发布到looper队列中,浓缩咖啡也不会等待更新
在这种情况下,你应该自己注册。您可以在googlesamples/android架构组件nice-sample中找到如何实现定制,并在执行测试之前设置空闲资源
因此,您必须将这些类复制到您的测试中
并将以下规则添加到测试类中:
@Rule
@JvmField
val dataBindingIdlingResourceRule = DataBindingIdlingResourceRule(activityRule)
executePendingBindings
应该足够了:在调用该方法时,绑定将立即执行,而不是在Choreographer
的下一帧执行,这也是我最初的想法。但事实证明,测试在AndroidJUnit线程上运行,executePendingBindings必须在主线程上运行。在Main上调度它的速度不够快,或者阻塞不足以在AndroidJUnit线程上进行失败的断言。您找到解决方案了吗?我有一个类似的问题,在espresso测试期间,错误的值被传递到数据绑定,但是如果我添加一个断点并等待片刻,它将发送正确的值,视图将被正确绑定,espresso将发现视图只是一个可怕的系统时钟。睡眠(…)目前,这个bug报告提到了使用反射的解决方法。但我无法让它工作。有人成功了吗?对我来说不管用。此操作失败,因为“accessFlags”的NoSuchFieldException。但我在Android的Field类上看到accessFlags。不知道为什么我会失败。我在棒棒糖模拟器上运行了它。@rpattabi您也可以在“accessFlags”之前尝试“modifiers”,如前所述。让我知道这是否有效。我应该注意到,这个解决方案在使用实际设备时有效,因此在模拟器jvm中运行测试时失败是有道理的。我在链接中写了您提供的信息:-)“修饰符”用于桌面jvm,“accessFlags”用于安卓jvm。它们对我都不起作用。我在实际设备上进行了检查,没有异常,但不清楚这是否会使espresso等待数据绑定。@rpattabi我将修改我的答案,以包括在桌面jvm上运行测试的情况。我正在为Java文件查找此类,但everywhere都有Kotlin文件。此外,此应用程序是按片段制作的,但我的应用程序是按活动制作的。我们正在跟踪一个更好的解决方案