【问题标题】:Testing a click on an Android ListView with ActivityUnitTestCase使用 ActivityUnitTestCase 测试对 Android ListView 的点击
【发布时间】:2015-08-10 10:12:14
【问题描述】:

我已经实现了一个ListView,它在单击列表项时启动一个新的Activity。当我手动测试它时,它工作得很好。但是当我尝试使用ActivityUnitTestCase 进行自动化测试时,我得到一个NullPointerException,好像ListView 是空的。

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 是空的?如何强制它使用正确的孩子更新自己?

【问题讨论】:

  • 你试过performItemClick()吗?
  • 使用performItemClick(),代码会更远一点,直到onItemClick 方法的clickedItem.getText() 部分。一旦到达那里,就会引发 NPE,因为提供的 viewnull(因为 getChildAt(0) 返回 null)。更新问题描述以使其更清晰。

标签: android unit-testing android-listview android-activity android-testing


【解决方案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);

【讨论】:

    【解决方案2】:

    这是因为列表视图尚未绘制。在尝试访问其单元格之前,您应该等待它被绘制

    【讨论】:

    • 这是有道理的。但是如何让程序等待列表的绘制呢? setUpTest()方法中应该添加哪一行代码?
    • 我不得不说我也在寻找关于这个问题的最佳实践。现在,我使用 Thread.sleep 调用。
    猜你喜欢
    • 1970-01-01
    • 2014-08-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-11-27
    • 2021-06-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多