为什么在 Android API 22 上的 Espresso 测试中 IdlingResource 为空?

Why is IdlingResource null in Espresso tests on Android API 22?

编辑: 我已经在 Android API 22 和 API 19 上的两个设备上测试了以下内容,一个在 API 19 上没有问题。知道版本之间的区别是什么吗?

我正在使用与示例 here 相同的 IdlingResource 为我的 Android 设置浓缩咖啡测试。

我的测试设置:

@Rule
public ActivityTestRule<MainActivity> mMainActivity =
        new ActivityTestRule(MainActivity.class);

private IdlingResource mIdlingResource;

@Before
public void registerIdlingResource() {
    mIdlingResource = mMainActivity.getActivity().getIdlingResource();
    IdlingRegistry.getInstance().register(mIdlingResource);
}

在我的 Activity 中,每次更改空闲状态时,我都会调用:

if (mIdlingResource != null) {
    mIdlingResource.setIdleState(false);
} else {
    Log.d("error ", "idle resource is null");
}

我的问题是在尝试更改 activity 中的空闲状态时出现的——在创建 activity 和 IdlingResource 可用之间似乎存在延迟。

在序列的第一个测试中,IdlingResource 永远不可用——因此我无法将 IdlingResource 的初始值设置为 false,然后再切换回 true。这似乎是由 this article:

中描述的注释生命周期引起的

据我所知,Activity 是由 @Rule 创建的,然后 IdlingResource 在 @Before 中实例化。由于 Activity 已经是 运行,因此在我尝试更改状态的每个点空闲资源都为空。

在随后的测试中,只跳过了 setIdleState 的第一个实例(发生在 onCreate 中)——也许与 @Rule 的 Activity 生命周期有关? -- 但其他人按预期运行。

是否有最佳实践让@Rule 和@Before 在第一次测试前按顺序工作?

您可以在 activity 中使用 static IdlingResource。在启动后台任务之前初始化 mIdlingResource(我不包括初始化代码,因为您已经编写了它)。

private static IdlingResource mIdlingResource;

//Getter for mIdlingResource
public IdlingResource getmIdlingResource() {
    return mIdlingResource;
}

然后您可以从您的测试中访问这个静态资源,而不是创建一个新变量。

@Before
public void registerIdlingResource() {
    IdlingRegistry.getInstance().register(mMainActivity.getActivity().getmIdlingResource());
}

那么 mIdlingResource 在 Activity.

中不会为 null

注意 - Google 建议使用 CountingIdlingResource。您可以在此处找到实现 - https://developer.android.com/reference/android/support/test/espresso/idling/CountingIdlingResource

更新: 检查评论中的代码后。

当您在注册时第一次调用它时,您的 IdlingResource 将被创建。

只需在 activity 的 onCreate() 中调用 getIdlingResource() 一次(或在调用 setIdleState 之前)。其余代码保持不变。它不会创建重复项,因为在初始化之前执行了 null 检查。

解决 activity 在 IdlingResource 可用之前启动问题的最佳解决方案是设置规则,使其不会启动 activity。这种方法的好处是你不必在Activity.

中手动注册IdlingResource

要实施此解决方案,请使用 ActivityTestRule

的以下构造函数

ActivityTestRule(Class<T> activityClass, boolean initialTouchMode, boolean launchActivity)

所以代码看起来像:

@Rule
public ActivityTestRule<MainActivity> mMainActivity =
        new ActivityTestRule(MainActivity.class, false, true);

private IdlingResource mIdlingResource;

@Before
public void registerIdlingResource() {
    mIdlingResource = mMainActivity.getActivity().getIdlingResource();
    IdlingRegistry.getInstance().register(mIdlingResource);
    mMainActivity.launchActivity(new Intent());
}