Тестирование щелчка в Android ListView с помощью ActivityUnitTestCase

Я реализовал ListView, который запускает новый Activity при нажатии элемента списка. Когда я проверяю его вручную, он работает отлично. Но когда я пытаюсь выполнить автоматизированный тест с ActivityUnitTestCase, я получаю NullPointerException, как если бы ListView был пуст.

Основная активность (частичная):

public class MainActivity extends ListActivity {

  @Override
  protected void onResume() {
    super.onResume();

    String[] items = new String[] {"item 1", "item 2"};
    ArrayAdapter<String> adapter = new ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, items);
    setListAdapter(adapter);

    getListView().setOnItemClickListener(new OnItemClickListener () {

      @Override
      public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
        TextView clickedItem = (TextView) view;
        CharSequence clickedItemText = clickedItem.getText(); // throws a NullPointerException when running testWithPerformItemClick()!
        Intent intent = new Intent(MainActivity.this, ItemDisplayActivity.class);
        intent.putExtra("parameter", clickedItemText);
        startActivity(intent);
      }
    });
  }
}

Неудачный тестовый код:

public class MainActivityTest extends ActivityUnitTestCase<MainActivity> {

  ListView listView;
  View child0;

  public MainActivityTest() {
    super(MainActivity.class);
  }

  private void setUpTest() {
    MainActivity activity = startActivity(new Intent(), null, null);
    getInstrumentation().callActivityOnStart(activity);
    getInstrumentation().callActivityOnResume(activity);
    listView = (ListView) activity.findViewById(android.R.id.list);
    child0 = listView.getChildAt(0); // returns null!
  }

  public void testWithPerformClick() {
    setUpTest();

    child0.performClick(); // throws a NullPointerException!

    Intent startedIntent = getStartedActivityIntent();
    assertEquals("item 1", startedIntent.getStringExtra("parameter"));
  }

  public void testWithPerformItemClick() {
    setUpTest();
    long itemId = listView.getAdapter().getItemId(0);

    listView.performItemClick(child0, 0, itemId); // throws a NullPointerException!

    Intent startedIntent = getStartedActivityIntent();
    assertEquals("item 1", startedIntent.getStringExtra("parameter"));
  }

Оба метода тестирования не работают, потому что listView.getChildAt(0) возвращает null. Почему ListView пусто? Как я могу заставить его обновить себя с правильными детьми?


person lacton    schedule 31.08.2013    source источник
comment
Пробовали ли вы performItemClick()?   -  person Ibungo    schedule 08.11.2013
comment
Используя performItemClick(), код становится немного дальше, вплоть до части clickedItem.getText() метода onItemClick. Оказавшись там, возникает NPE, потому что предоставленный view равен null (поскольку getChildAt(0) возвращает null). Обновление описания проблемы, чтобы сделать это более понятным.   -  person lacton    schedule 09.11.2013


Ответы (2)


Согласно документации, если вы предпочитаете функциональный тест, вам следует использовать ActivityInstrumentationTestCase2. . Для выполнения щелчка это работает лучше. Ответ @fewe правильный, вам нужно дождаться рисования списка, чтобы дождаться загрузки фрагмента, вы можете использовать getInstrumentation().waitForIdleSync();

Попробуйте что-нибудь вроде этого.

public class ActivityTests extends
    ActivityInstrumentationTestCase2<Activity>

final ListView list = (ListView) mActivity.findViewById(R.id.listId);
         assertNotNull("The list was not loaded", list);
         getInstrumentation().runOnMainSync(new Runnable() {
             @Override
             public void run() {

                 list.performItemClick(list.getAdapter().getView(position, null, null),
                         position, list.getAdapter().getItemId(position));
             }

         });

 getInstrumentation().waitForIdleSync();

Тогда вы не сможете проверить, например, был ли загружен фрагмент.

  mFragment frag = mActivity.getFragment();
  assertNotNull("Fragment was not loaded", frag);
person dinhokz    schedule 27.05.2014

Это связано с тем, что список еще не нарисован. Вы должны подождать, пока он будет нарисован, прежде чем пытаться получить доступ к его ячейкам.

person fewe    schedule 15.11.2013
comment
Это имело бы смысл. Но как заставить программу ждать отрисовки списка? Какую строку кода нужно добавить в метод setUpTest()? - person lacton; 16.11.2013
comment
Я должен сказать, что ищу передовой опыт в этом вопросе. На данный момент я использую вызов Thread.sleep. - person fewe; 17.11.2013