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

Viewed 95

The layout of my activity is basically this (simplified to illustrate the problem). Basically there's not much space for the ListView to appear if the device has a small screen, because other views take up all the space:

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

My activity code sets up the item click listener as follows:

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

My unit test taps on the first item in the list:

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

With Robolectric 4.2.1, my click listener is called with a non-null view. With Robolectric 4.3, it's called with a null view.

1 Answers

Summary: The solution is to specify a larger device height for this test with the @Config(qualifiers="h780dp") annotation.

Details: After some debugging, I discovered that with Robolectric 4.2.1, the height of the ListView was 146 (top=680, bottom=826), but with Robolectric 4.3 it's 0 (top=680, bottom=680). The default device height used by Robolectric is 470, which isn't enough to display the list. The list doesn't have any child views with Robolectric 4.3.

The implementation of shadowOf(list).performItemClick(0) is found in ShadowAdapterView from robolectric, and is:

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

With Robolectric 4.3, getChildAt(position) returns null, which is what is forwarded to the click listener.

The workaround is to specify a larger device screen for this test. For example:

@Test
@Config(qualifiers="h780dp")
Related