如何从 Espresso 中获取视图以传递到 IdlingResource?

How to get a view from within Espresso to pass into an IdlingResource?

我基本上有一个自定义 IdlingResource,它接受一个 View 构造函数参数。我找不到任何地方真正谈论如何实现它。

我正在尝试使用这个答案:

如您所见,它需要 ViewPager,但是当我在测试 class 中注册 IdlingResource 时,我不确定如何获得我的查看。

我试过 findViewById(),我试过获取当前 运行 activity 然后调用 findViewById(),但没有成功。

有人知道在这种情况下该怎么办吗?

我还没有在 Espresso 中使用过 IdilingResources,但是你看过这些文章了吗:

另请查看官方Android文档:Idling Resources (reference)

为了回答你的问题,

  • 最好的方法是将其中一个视图的实例传递到 class 的构造函数中。检查:Calling findViewById() from outside an activity

  • 另一种方法是根据上下文获取视图。检查 android - How to get view from context?

这是一个取自上面 link 的例子:

Starting with a context, the root view of the associated activity can be had by

View rootView = ((Activity)_context).Window.DecorView.FindViewById(Android.Resource.Id.Content);

In Raw Android it'd look something like:

View rootView = ((Activity)mContext).getWindow().getDecorView().findViewById(android.R.id.content)

Then simply call the findViewById on this

View v = rootView.findViewById(R.id.your_view_id);

这可能也有用:How to call getResources() from a class which has no context?

希望对您有所帮助

想通了。要让视图传递到空闲资源中,您所要做的就是获取 ActivityTestRule

的成员变量

例如:

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

然后只需调用 getActivity().findViewById(R.id.viewId)

所以最后的结果是:

activityTestRule.getActivity().findViewById(R.id.viewId);

只要同一 activity 中的测试 运行,接受的答案就有效。但是,如果测试导航到另一个 activity activityTestRule.getActivity() 将 return 错误 activity (第一个)。为了解决这个问题,可以创建一个辅助方法 returning 一个实际的 activity:

public Activity getCurrentActivity() {
    final Activity[] currentActivity = new Activity[1];
    InstrumentationRegistry.getInstrumentation().runOnMainSync(new Runnable() {
        @Override
        public void run() {
            Collection<Activity> allActivities = ActivityLifecycleMonitorRegistry.getInstance()
                    .getActivitiesInStage(Stage.RESUMED);
            if (!allActivities.isEmpty()) {
                currentActivity[0] = allActivities.iterator().next();
            }
        }
    });
    return currentActivity[0];
}

然后可以这样使用:

Activity currentActivity = getCurrentActivity();
if (currentActivity != null) {
    currentActivity.findViewById(R.id.viewId);
}

如果您使用 androidx.test.ext.junit.rules 中的 ActivityScenarioRule(因为 ActivityTestRule "will be deprecated and eventually removed from library in the future"),您可以获取 Activity 实例并调用 findViewById 方法:

import androidx.test.ext.junit.rules.activityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4

@RunWith(AndroidJUnit4::class) {

    @get: Rule
    var testRule = activityScenarioRule<MainActivity>()

    @Test
    fun mainTestCase() {
        testRule.scenario.onActivity { activity ->
            val view = activity.findViewById<YourView>(R.id.view)
        }
    }
}