3

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

MainActivity (частичные):

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 пуст? Как я могу заставить его обновить себя с нужными детьми?

+0

Вы пробовали [ 'performItemClick()'] (http://developer.android.com/reference/android/widget/AdapterView.html#performItemClick (android.view.View,% 20int,% 20long))? – Ibungo

+0

Используя 'performItemClick()', код становится немного дальше, до '' clickedItem.getText() 'метода' onItemClick'. Когда-то там NPE возникает, потому что предоставленный 'view' является' null' (потому что getChildAt (0) возвращает null). Обновление описания проблемы, чтобы сделать это более понятным. – lacton

ответ

0

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

+0

Это имело бы смысл. Но как вы заставляете программу ждать рисования списка? Какую строку кода следует добавить в метод 'setUpTest()'? – lacton

+0

Должен сказать, что я ищу наилучшую практику по этому вопросу. На данный момент я использую вызов Thread.sleep. – fewe

1

Согласно documentation, если вы предпочитаете функциональный тест, вы должны использовать 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);