解读Android官方MVP项目单元测试(3)

发表于:2016-06-29来源:简书作者:geniusmart点击数: 标签:单元测试
连上设备,跑起UT,会自动启动相应的Activity界面,做相应的操作后进行测试。 总结:Espresso好强大,而且这一层的测试站在用户的角度,所有逻辑是黑盒

连上设备,跑起UT,会自动启动相应的Activity界面,做相应的操作后进行测试。

总结:Espresso好强大,而且这一层的测试站在用户的角度,所有逻辑是黑盒,在功能层面测试输入(用户操作)输出(用户得到的界面反馈),而技术层面,由于界面是所有层的入口,得到输出后,除了测试View层本身的逻辑之外,其实已经粗糙的覆盖了M和P的逻辑了。

Model层的测试

关于Model层的测试,首先要了解下该项目中,model层的设计,类层次如下图所示:


Model层的类图
  • TasksLocalDataSource:负责本地数据库增删改查操作
  • TasksRemoteDataSource:负责网络请求(该项目中用handler.postDelayed()延时来模拟网络请求)
  • TasksRepository:相当于整个Model层的门面,根据逻辑判断决定数据来自于本地数据库或是网络。Presenter层只与它打交道。

根据以上分析,可见对Model层的测试要完整的覆盖这三个类。

  1. 我们先看门面TasksRepository的测试,先看看这个类中有关获取待办任务列表的流程图:


    TasksRepository流程图

    所以对于TasksRepository来讲,测试的内容主要是验证1,2,3的逻辑是否在相应的输入下覆盖到位,对于1,2,3的数据准确性无需关心,由各自DataSource去验证,因此它的测试与Android环境无关,用Junit+Mockito测试。要完整覆盖的话,需要多个测试case,篇幅有限,这里只讲第2种。这个测试类是TasksRepositoryTest,代码如下:

    @Test
    public void getTasksWithDirtyCache_tasksAreRetrievedFromRemote() {
     //将数据设置为脏数据
     mTasksRepository.refreshTasks();
     //数据为脏数据,因此此时需要从网络获取
     mTasksRepository.getTasks(mLoadTasksCallback);
    
     //验证第2种情况:用TasksRemoteDataSource调用getTasks()获取数据后返回
     setTasksAvailable(mTasksRemoteDataSource, TASKS);
    
     //验证第1种情况没有发生
     verify(mTasksLocalDataSource, never()).getTasks(mLoadTasksCallback);
     //验证TasksRemoteDataSource执行了回调函数
     verify(mLoadTasksCallback).onTasksLoaded(TASKS);
    }

    其中,setTasksAvailable()代码如下:

    private void setTasksAvailable(TasksDataSource dataSource, List<Task> tasks) {
     //验证第2种情况:使用TasksRemoteDataSource调用getTasks()
     verify(dataSource).getTasks(mTasksCallbackCaptor.capture());
     //执行回调 函数
     mTasksCallbackCaptor.getValue().onTasksLoaded(tasks);
    }
  2. 接下来是是TasksLocalDataSource的测试。该测试与数据库有关,因此依赖于Android环境,且要验证数据存取的准确性,因此需要做一些断言,使用AndroidJUnitRunner进行测试,这个类是TasksLocalDataSourceTest,代码如下:

    @Test
    public void getTasks_retrieveSavedTasks() {
    //事先往DB中插入两条数据
    final Task newTask1 = new Task(TITLE, "");
    mLocalDataSource.saveTask(newTask1);
    final Task newTask2 = new Task(TITLE, "");
    mLocalDataSource.saveTask(newTask2);
    
     
    
    
    
               

    原文转自:http://www.jianshu.com/p/cf446be43ae8