Home » Android » android – Robolectric test ListView not updating after value changes in adapter

android – Robolectric test ListView not updating after value changes in adapter

Posted by: admin June 15, 2020 Leave a comment

Questions:

I have created a layout with a ListView that updates values in it depending on which of the 2 given buttons are pressed. Pressing the button labelled Odds clears all values and adds odd numbers up until 20. Pressing evens does the same except for even numbers. This works fine when emulated or tried on a real device. Below is the activity code.

public class ListViewActivity extends Activity {

    private ListView mainListView;
    private ArrayAdapter<String> listAdapter;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.robolectric_test_main);

        mainListView = (ListView) findViewById(R.id.mainListView);

        ArrayList<String> numbersList = new ArrayList<String>();
        for (int i = 1; i < 21; i++) {
            numbersList.add(String.valueOf(i));
        }

        listAdapter = new ArrayAdapter<String>(this, R.layout.robolectric_listview_row, numbersList);

        mainListView.setAdapter(listAdapter);
    }

    public void onOddsClicked(View view) {
        listAdapter.clear();
        for (int i = 1; i < 21; i += 2) {
            listAdapter.add(String.valueOf(i));
        }
    }

    public void onEvensClicked(View view) {
        listAdapter.clear();
        for (int i = 2; i < 21; i += 2) {
            listAdapter.add(String.valueOf(i));
        }
    }
}

However when trying to test it with Robolectric the ListView is never updated even though the adapter has value modifications. Here is my test code.

@RunWith(RobolectricTestRunner.class)
public class ListViewActivityTest {

    private ListViewActivity listViewActivity;
    private Button oddsButton;
    private Button evensButton;
    private ListView numbersList;

    @Before
    public void setUp() throws Exception {
        listViewActivity = Robolectric.buildActivity(ListViewActivity.class).create().start().resume().visible().get();
        assignFields();
    }

    private void assignFields() {
        oddsButton = (Button) listViewActivity.findViewById(R.id.oddsButton);
        evensButton = (Button) listViewActivity.findViewById(R.id.evensButton);
        numbersList = (ListView) listViewActivity.findViewById(R.id.mainListView);
    }

    @Test
    public void odds() throws Exception {
        // check all numbers are odd
        Robolectric.clickOn(oddsButton);
        Robolectric.runUiThreadTasksIncludingDelayedTasks();
        for (int i = 0; i < numbersList.getChildCount(); i++) {
            TextView number = (TextView) numbersList.getChildAt(i);
            String numberString = number.getText().toString();
            int parsedInt = Integer.parseInt(numberString);
            assertTrue((parsedInt % 2) == 1);
        }
    }

    @Test
    public void evens() throws Exception {
        // check all numbers are even
        Robolectric.clickOn(evensButton);
        Robolectric.runUiThreadTasksIncludingDelayedTasks();
        for (int i = 0; i < numbersList.getChildCount(); i++) {
            TextView number = (TextView) numbersList.getChildAt(i);
            String numberString = number.getText().toString();
            int parsedInt = Integer.parseInt(numberString);
            assertTrue((parsedInt % 2) == 0);
        }
    }

}

Can you please let me know what I need to do in order to trigger the update on the ListView through Robolectric.

How to&Answers:

In robolectric you must call ShadowListView.populateItems() to get adapter changes

Robolectric 3.0

ShadowListView shadowListView = Shadows.shadowOf(mListView);
shadowListView.populateItems();

Robolectric 2.0

ShadowListView shadowListView = Robolectric.shadowOf(listView);
shadowListView.populateItems(); 

Answer:

Just to update the answer to Robolectric 3.0

 ShadowListView shadowListView = Shadows.shadowOf(mListView);
    shadowListView.populateItems();