解读Android官方MVP项目单元测试(4)
发表于:2016-06-29来源:简书作者:geniusmart点击数:
标签:单元测试
//执行获取数据列表的方法,并在回调函数中进行断言 mLocalDataSource.getTasks( new TasksDataSource.LoadTasksCallback() { @Override public void onTasksLoaded (ListTask tasks) { //断言
mLocalDataSource.getTasks(
new TasksDataSource.LoadTasksCallback() {
@Override
public void onTasksLoaded(List<Task> tasks) {
assertNotNull(tasks);
assertTrue(tasks.size() >=
2);
boolean newTask1IdFound =
false;
boolean newTask2IdFound =
false;
for (Task task: tasks) {
if (task.getId().equals(newTask1.getId())) {
newTask1IdFound =
true;
}
if (task.getId().equals(newTask2.getId())) {
newTask2IdFound =
true;
}
}
assertTrue(newTask1IdFound);
assertTrue(newTask2IdFound);
}
@Override
public void onDataNotAvailable() {
fail();
}
});
}
最后来看看跟网络请求相关的TasksRemoteDataSource的测试
Google并没有对这个类本身进行测试,但是对其他层依赖网络请求数据进行测试的场景做了支持。试想一下,通过上面的分析,我们知道View层是真刀真枪的在模拟用户的操作进行测试,如果某个测试case需要发起网络请求,此时我们不知道何时才能返回数据,且由于网络状况等原因可能导致请求失败,种种不确定因素下,是不可能完成一个测试的,解决的办法很简单,就是对网络请求进行Fake,这个类是FakeTasksRemoteDataSource
,原理便是当需要用到TasksRemoteDataSource时,不会真正使用该类,而是注入FakeTasksRemoteDataSource,返回事先定义好的数据。
为此,这个项目在项目结构和代码方面提供了很多支撑,体现在:
-
提供了mock和prod两种Flavors
-
两种Flavor分别提供了Injection,注入Fake类或真实类
-
所有与网络请求相关的测试代码存放在androidTestMock下
总结:Model层的测试时而在androidTest写UT,时而在test里写,时而在androidTestMock里,有点精神分裂的感觉。但是,真的好清晰,看起测试的结构来非常舒服。
MVP的单元测试架构总结
通过这个例子,我们已经了解了MVP各层之间的职责以及对应的测试内容,接下来做个总结,首先看下MVP测试架构图:
MVP测试架构图
-
View层
-
职责:MVP模式下,View层终于扬眉吐气了,View本身该做的事情都能做了,比如UI布局,数据渲染,点击按钮交互等等
-
测试方式:以正常小QA的测试思维方法,就可以来定义这一层的测试方式,测试过程中需要真机或模拟器,并做真实的操作。
-
测试选型:依赖于Android环境,用谷歌强大的Espresso+AndroidJUnitRunner,Espresso用于模拟和验证各种各样的UI操作,代码存放于AndroidTest中。
-
Presenter层:
-
职责:这一层是拉皮条的,负责M和V层的对接,所以有较少的处理输入输出的机会,他只用来控制逻辑,去调用相应的Model和View的逻辑。
-
测试选型:他的职责决定了他很少去断言输入输出,测试逻辑覆盖的路径是否正确即可,因此他与Android环境无关,用Junit+Mockito测试即可,代码存放于test中。
-
Model层