Robolectric, Problems with clicking list items

2019-04-24 02:36发布

问题:

I have been struggling with this problem a bit, and I think I am not getting something fundamental about Robolectric. Usually some google searches can help me get to the bottom of this type of problem, but between that and looking at the sample code I am not finding anything of use.

I am trying to emulate a click on a list view item and check that an activity is launched after the click. I keep getting back that the current activity I am testing is the resulting activity. I tried removing all of the list item clicking code and checking the resulting activity, and this came back as the InstallationListActivity that I am testing. So I came to the conclusion that the list view item is not being clicked, and I am just not sure why. The system logs that I have set up in the testing code below are the values that I expect them to be. The list is 13 items, and the getChildAt(0) returns the header. I would think that getting the first item (getChildAt(1)) and calling performClick on it or its child text view would launch my expected activity, but that doesn't seem to be the case. Anyway, here is the robolectric/testing code I am using:

    @Before
    public void setUp() {
        mAppLaunch = new ApplicationLaunchActivity();
        mAppLaunch.onCreate(null);
        mActivity = new InstallationListActivity();
        mActivity.onCreate(null);
    }

    @Test
    public void shouldHaveNonEmptyInstallationList() throws Exception {
        assert(mActivity.installationListCount() > 0);
    }

    @Test
    public void shouldHaveSameNumberOfElements() throws Exception {
        ListView installationListView = (ListView) mActivity.getListView();

        ShadowListView shadowListView = shadowOf(installationListView);

        assert(shadowListView.getChildCount() == mActivity.installationListCount());
    }

    @Test
    public void pressingTheFirstItemInTheListShouldLaunchVenueListActivity() {
        ListView installationListView = (ListView) mActivity.findViewById(android.R.id.list);

        System.out.println("qty: " + installationListView.getChildCount());
        System.out.println("class: " + installationListView.getChildAt(0).getClass());
        System.out.println("class: " + installationListView.getChildAt(1).getClass());
        System.out.println("class: " + installationListView.getChildAt(2).getClass());
        System.out.println("class: " + installationListView.getChildAt(3).getClass());
        System.out.println("class: " + installationListView.getChildAt(4).getClass());

        LinearLayout firstItemLayout = (LinearLayout) installationListView.getChildAt(1);
        TextView firstItem = (TextView) firstItemLayout.getChildAt(0);

        ShadowTextView shadowFirstItem = shadowOf(firstItem);
        ShadowLinearLayout shadowLayout = (ShadowLinearLayout) shadowOf(firstItemLayout);

        shadowLayout.performClick();
        shadowFirstItem.performClick();

        clickOn(firstItem);
        clickOn(firstItemLayout);

        System.out.println("class: " + firstItemLayout.getChildAt(0).getClass());
        System.out.println("Layout shadow" + shadowOf(firstItemLayout).getClass());
        System.out.println("First Item Text: " + shadowFirstItem.getText());

        ShadowActivity shadowActivity = shadowOf(mActivity);
        Intent startedIntent = shadowActivity.getNextStartedActivity();
        assertNotNull(startedIntent);
        ShadowIntent shadowIntent = shadowOf(startedIntent);

        assertThat(shadowIntent.getComponent().getClassName(), equalTo(VenueListActivity.class.getName()));
    }
}

Here is the layout's I am using to build the list view:

This is list.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent">
    <ListView android:id="@android:id/list"
              android:layout_width="fill_parent"
              android:layout_height="fill_parent"
              android:cacheColorHint="#00000000"
              android:background="@drawable/background"/>
</LinearLayout>

list_item.xml


<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
              android:id="@+id/list_item"
              android:layout_height="fill_parent"
              android:layout_width="fill_parent">
    <TextView android:id="@+id/list_item_text"
              style="@style/tw_list_font"
              android:layout_width="match_parent"
              android:layout_height="wrap_content"
              android:textAppearance="?android:attr/textAppearanceLarge"
              android:gravity="center_vertical"
              android:paddingLeft="6dip"
              android:minHeight="?android:attr/listPreferredItemHeight" />
</LinearLayout>

And here is the code that initializes the list:

InstallationListActivity.java

setContentView(R.layout.list);
        final ListView installationListView = getListView();
        LayoutInflater inflater = getLayoutInflater();
        ViewGroup header = (ViewGroup) inflater.inflate(R.layout.header, installationListView, false);
        TextView headerText = (TextView) header.findViewById(R.id.header_text);
        headerText.setText("Installations On Live"); // TODO: This should not be hardcoded
        installationListView.addHeaderView(header, null, false);

        setListAdapter(new ArrayAdapter<Installation>(this, R.layout.list_item, R.id.list_item_text, mInstallations));

        // Click event
        installationListView.setClickable(true);
        installationListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> adapterView, View view, int position, long arg1) {
                Installation installationClicked = (Installation) installationListView.getItemAtPosition(position);
                if (LOCAL_LOG) {
                    Log.d(LOG_TAG, "Installation: " + installationClicked.toString() + " clicked.");
                    Log.d(LOG_TAG, installationClicked.toString() + " has installationDirectory: " +
                            installationClicked.rootDir);
                }
                AppState.installation = installationClicked;
                AppState.serverInstallationName = installationClicked.rootDir;
                Intent venueListIntent = new Intent(InstallationListActivity.this, VenueListActivity.class);
                startActivity(venueListIntent);
            }
        });

Any help is much appreciated! Thanks a ton!

回答1:

Try the helper method performItemClick:

Robolectric.shadowOf(listView).performItemClick(position);