Wen

Android MVP学习笔记 (下) - MVP和Tests

通过对两个demo的分析,相信大家已经知道MVP是怎么回事了。那现在可以回过头来想想,说了这么久的MVP架构,这个架构到底有什么好处呢?

MVP优点


MVP本质上是把业务逻辑和UI分的更彻底了,这样带来的好处有很多,比如结构更清晰,更好的拓展性,可复用性等,但我觉得最主要的一点,是方便写单元测试!

为什么MVP结构利于单元测试?这篇文章说的很好:

MVP结构最大的特点是,P将逻辑和UI分开了。即P 中没有任何Android相关的代码,比如Toast啊、setText等等。这意味着~ 你可以针对Presenter写junit测试了。只对java代码的测试,不用涉及任何UI!!!不用运行模拟器的测试!!!!!速度起飞的测试!!!!!!!!

下面还是以Google的TODO-MVP为例,看看在MVP模式下是如何写Unit Test的。

Google Todo 中的Test


首先先说两句,Google的 Todo MVP App中包含了Test的方方面面,既有Unit Test (在src/test目录) 也有UI Test (在src/androidTestsrc/androidTestMock目录),可以当作学习Android Test的例子,感兴趣的推荐大家去看Android Codelab出品的Android Test,写的非常详细,强势推荐。

这里只看Unit Test,项目中所有的Unit Test都放在了src/test目录下,而且一个Presenter对应一个Test文件。

选取其中最熟悉的TaskPresenter对应的TaskPresenterTest出来,先看最简单的一个。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class TasksPresenterTest {
@Mock
private TasksRepository mTasksRepository;
@Mock
private TasksContract.View mTasksView;
...
@Test
public void clickOnFab_ShowsAddTaskUi() {
// When adding a new task
mTasksPresenter.addNewTask();
// Then add task UI is shown
verify(mTasksView).showAddTask();
}
}

可以看到,这里用Unit Test的形式来验证逻辑正确非常简单,当Presenter上的addNewTask()被call到时,我只需要知道是不是call到View上的showAddTask()就可以了,而完全不用管View里面的具体实现,也自然不会调用到Android内部函数。再来看一个栗子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public class TasksPresenterTest {
@Test
public void loadCompletedTasksFromRepositoryAndLoadIntoView() {
// Given an initialized TasksPresenter with initialized tasks
// When loading of Tasks is requested
mTasksPresenter.setFiltering(TasksFilterType.COMPLETED_TASKS);
mTasksPresenter.loadTasks(true);
// Callback is captured and invoked with stubbed tasks
verify(mTasksRepository).getTasks(mLoadTasksCallbackCaptor.capture());
mLoadTasksCallbackCaptor.getValue().onTasksLoaded(TASKS);
// Then progress indicator is hidden and completed tasks are shown in UI
verify(mTasksView).setLoadingIndicator(false);
ArgumentCaptor<List> showTasksArgumentCaptor = ArgumentCaptor.forClass(List.class);
verify(mTasksView).showTasks(showTasksArgumentCaptor.capture());
assertTrue(showTasksArgumentCaptor.getValue().size() == 2);
}
}

这个是测试当Customer想只显示已完成的任务的逻辑,理论上最好一个test case只cover一个函数,但这里运行了Presenter的两个函数,但这也是符合用户用这个app的流程,算是稍微特殊的一点吧。

总结


关于Unit Test这里就不做深入的讲解了,感兴趣的请看文中引用到的两个链接。关于MVP的学习到这里就到一段落了,希望能起到抛砖引玉的作用。

转载请注明出处:http://zhaowen.io/post/Android_MVP_Learning_Notes_3/