自从升级到 Robolectric 4.3,ListView 的 onItemClickListener 得到一个空视图

Since upgrading to Robolectric 4.3, a ListView's onItemClickListener is getting a null View

我的activity的布局基本就是这样(为了说明问题做了简化)。如果设备有一个小屏幕,基本上 space 不会出现 ListView,因为其他视图占据了所有 space:

<LinearLayout orientation="vertical">
    <SomeBigView
        layout_width="match_parent"
        layout_height="680dp"/>
    <ListView
        layout_width="match_parent"
        layout_height="wrap_content" />
</LinearLayout>

我的 activity 代码设置项目点击监听器如下:

list.onItemClickListener = AdapterView.OnItemClickListener { _, view, _, _ ->
    Snackbar.make(view, "Clicked on $view", Snackbar.LENGTH_SHORT).show()
}

我的单元测试点击列表中的第一项:

val controller = Robolectric.buildActivity(MainActivity::class.java)
    .create().start().resume().visible()
val list: ListView = controller.get().findViewById(R.id.list)
shadowOf(list).performItemClick(0)

在 Robolectric 4.2.1 中,我的点击侦听器使用非空 view 调用。 在 Robolectric 4.3 中,它以 null 视图调用。

总结: 解决方案是使用 @Config(qualifiers="h780dp") 注释为该测试指定更大的设备高度。

详情: 经过一些调试,我发现在 Robolectric 4.2.1 中, ListView 的高度是 146 (top=680, bottom=826),但是 Robolectric 4.3 是 0 (top=680, bottom=680)。 Robolectric 使用的默认设备高度是 470,这不足以显示列表。该列表没有 Robolectric 4.3.

的任何子视图

shadowOf(list).performItemClick(0) 的实现在 robolectric 的 ShadowAdapterView 中找到,并且是:

public boolean performItemClick(int position) {
    return realAdapterView.performItemClick(realAdapterView.getChildAt(position),
        position, realAdapterView.getItemIdAtPosition(position));
}

使用 Robolectric 4.3,getChildAt(position) returns null,这是转发给点击侦听器的内容。

解决方法是为此测试指定更大的设备屏幕。例如:

@Test
@Config(qualifiers="h780dp")