浓缩咖啡 RecyclerView 错误 - 位置处没有视图持有者

9

我正在运行一个Espresso测试,以点击RecyclerView中的一个元素。

   onView(withId(R.id.recyclerList)).perform(RecyclerViewActions.actionOnItemAtPosition(2, click()));

然而,我遇到了以下错误:java.lang.IllegalStateException: No view holder at position

我已经确认视图id指向了我的RecyclerView,并且我的依赖关系如下:

  • com.android.support.test.espresso:espresso-core:2.2.2
  • com.android.support.test.espresso:espresso-contrib:2.2.2

2
你解决了吗?我也遇到了完全相同的问题,但没有人回答我的问题。 - ovalb
很遗憾,我无法解决 :-( - AdamHurwitz
请提供一个能够重现错误的 [mcve]。 - Code-Apprentice
3个回答

6

好的,我认为我曾经遇到过同样的问题,并成功解决它。

问题在于,除非您使用AsyncTask来填充RecyclerView,否则Espresso不会等待后台线程完成之后再执行下一个操作。

所以,它会搜索位于2号位置的项目,由于您的后台线程仍在运行且recycler view尚未加载,因此它会返回IllegalStateException。

即使我不建议这样做,但可以通过添加Thread.sleep()(适当的时间)来快速检查测试是否有效,就像这样:

    @Test
    public void myTest() {

        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        onView(withId(R.id.recyclerList))
                .perform(RecyclerViewActions.actionOnItemAtPosition(2, click()));

        //assert something
}

这个问题的更好(并且正确)的解决方案是使用Idling Resources

这个简短明了的视频帮助我理解如何使用IdlingResources(特别是CountingIdlingResources)。

现在你的UI测试应该是这样的:

    @Test
    public void myTest() {
        registerIdlingResources(/*put your IdlingResource here*/);

        onView(withId(R.id.recyclerList))
                .perform(RecyclerViewActions.actionOnItemAtPosition(2, click()));

        //assert something
}

我希望你已经受益。

1
我猜测,可能的问题是您在尝试执行操作时,您的项目实际上是不可见的。如果是这样,您可以尝试 onView(withId(R.id.recyclerList)).perform(RecyclerViewActions.scrollToPosition(2)) 然后再执行您的操作。

0

您可以使用CountingIdlingResource类来确保在调用increment()获取数据之前,您的数据已经加载到您的回收视图中,然后在数据加载完成后,在您的计数空闲对象上调用decrement()

首先要做的是添加依赖项以使用CountingIdlingResource

implementation 'androidx.test.espresso:espresso-idling-resource:3.3.0'

在你的Activity中定义一个类型为CountingIdlingResource的全局公有(public)变量。
public CountingIdlingResource idlingResource = new CountingIdlingResource("Loader");

“Loader”只是您的空闲资源的唯一标识符(来自文档:此资源应向Espresso报告的资源名称)。
然后,在从数据源获取数据之前,只需调用idlingResource.increment(),在获取数据后,只需调用idlingResource.decrement()
在您的RecyclerViewTest类中的最后一步是添加您的activity rule
@Rule
public ActivityScenarioRule<YourActivity> rule = new ActivityScenarioRule<>(YourActivity.class);

然后在你的测试方法内部

@Test
public void recyclerViewItemClick() {

    rule.getScenario().onActivity(new ActivityScenario.ActivityAction<YourActivity>() {
        @Override
        public void perform(YourActivity activity) {
            IdlingRegistry.getInstance().register(activity.idlingResource);
        }
    });

    onView(withId(R.id.rv)).perform(actionOnItemAtPosition(2, click()));
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接