如何测试Fragment中使用的自定义Array Adapter?
我正在开发一款私人Android应用,想给它写单元测试。目前已经完成了模型类的部分测试,但在测试Fragment里用到的自定义ArrayAdapter时卡壳了。作为Android测试新手,我知道得用Android测试而非普通单元测试,但获取Fragment上下文时出了问题。
尝试Robolectric的错误
一开始我用Robolectric写测试代码:
@RunWith(RobolectricTestRunner.class) public class MyFragmentTest { private MainActivity activity; private TripInputFragment fragment; @Before public void setup() { activity = Robolectric.buildActivity(MainActivity.class).create().visible().get(); fragment = new TripInputFragment(); activity.getSupportFragmentManager().beginTransaction().add(fragment, null).commit(); } @Test public void testFragment() { } @After public void tearDown() { activity.getSupportFragmentManager().beginTransaction().remove(fragment).commit(); } }
运行时报错:No virtual method getAnnotatedParameterTypes()
直接测试Adapter的情况
后来我放弃Robolectric,改用Instrumentation直接测试适配器:
@Test public void dayOfWeekAdapterTest() { Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext(); int resource = R.layout.list_item_layout; List<Trip> trips = new ArrayList<>(); trips.add(new Trip("Saturday", "Berlin", "Lisbon")); DayOfWeekAdapter adapter = new DayOfWeekAdapter(appContext, resource, trips); View view = adapter.getView(0, null, null); TextView dayOfWeektext = view.findViewById(R.id.trip_day_of_week); Log.i("view", String.valueOf(view.getId())); Log.i("view", trips.get(0).getDayOfWeek()); Log.i("view", (String) dayOfWeektext.getText()); assertEquals(trips.get(0).getDayOfWeek(), dayOfWeektext.getText()); }
这里文本内容的断言成功了,但getView()返回的视图ID是-1(后来发现是布局没设置ID导致的)。
核心疑问
现在我想知道:能不能直接用assertEquals断言两个View对象相等?还是必须给视图设置ID后通过ID来判断?
回答
直接断言View对象相等的问题:
直接用assertEquals(view1, view2)判断的是两个对象的内存地址是否一致,也就是是否是同一个实例。在Adapter的测试场景里,除非你能确保两次获取的View是同一个对象(比如复用了convertView),否则这种断言没有意义——因为getView()每次调用可能返回新的View实例,即使它们的布局和内容完全一样。通过ID判断的局限性:
给视图设置ID后用assertEquals(view1.getId(), view2.getId()),只能判断两个View的ID是否相同,但无法验证它们的布局结构、显示内容是否一致,所以这也不是完整的测试方式。正确的测试方式:
测试Adapter的getView(),核心应该是验证视图的内容是否符合预期(比如你之前做的文本断言),以及视图的结构是否正确(比如子View是否存在、属性是否正确)。如果需要判断两个View是否“等价”,应该逐一验证它们的关键属性:- 子View的内容(文本、图片等)
- 布局参数(宽高、边距等)
- 可见性状态
- 自定义View的特定属性
如果确实需要判断两个View实例是否是同一个(比如测试convertView复用逻辑),那可以直接用assertEquals比较对象,但这种场景比较少,大部分Adapter测试还是聚焦在内容和结构的正确性上。
内容的提问来源于stack exchange,提问作者Hjk

