原文:https://developer.android.com/training/testing/unit-testing/local-unit-tests.html

如果你的单元测试没有依赖或者只有简单的Android依赖,则应该在本地开发机器上运行测试。这种测试方法非常高效,因为它可以帮助你避免每次运行测试时将目标应用程序和单元测试代码加载到真机或模拟器上的开销。因此,运行单元测试的执行时间大大减少了。通过这种方法,你通常使用mock框架(如Mockito)来完成任何依赖关系。

### 设置测试环境

在你的Android Studio项目中,必须将本地单元测试的源文件存储在module-name/src/test/java/ 目录中。在创建新项目时,该目录已经存在。

你还需要配置项目的测试依赖,以使用JUnit 4框架提供的标准API。如果你的测试需要与Android依赖关系进行交互,请包含Mockito库以简化本地单元测试。要了解有关在本地单元测试中使用模拟对象的更多信息,请参阅模拟Android依赖关系。

在你的App程序的目录下找到build.gradle文件中,将这些库指定为依赖项:

dependencies {
    // Required -- JUnit 4 framework
    testCompile 'junit:junit:4.12'
    // Optional -- Mockito framework
    testCompile 'org.mockito:mockito-core:1.10.19'
}

### 创建本地单元测试类

你的本地单元测试类应该写成一个JUnit 4测试类。 JUnit是Java最流行和广泛使用的单元测试框架。这个框架的最新版本,JUnit 4,允许你用比前一版本更清晰,更灵活的方式编写测试。与以前的基于JUnit 3的Android单元测试方法(使用JUnit 4)不同,你不需要扩展junit.framework.TestCase类。也不需要在测试方法名称前加上“test”关键字,或者使用junit.framework或junit.extensions包中的任何类。

要创建基本的JUnit 4测试类,请创建一个包含一个或多个测试方法的Java类。 测试方法从 @Test 注释开始,包含代码来练习和验证要测试的组件中的单个功能。

以下示例显示了如何实现本地单元测试类。 测试方法emailValidator_CorrectEmailSimple_ReturnsTrue验证被测试的应用程序中的isValidEmail()方法是否返回正确的结果。

import org.junit.Test;
import java.util.regex.Pattern;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; public class EmailValidatorTest {     @Test
    public void emailValidator_CorrectEmailSimple_ReturnsTrue() {
        assertThat(EmailValidator.isValidEmail("name@email.com"), is(true));
    }
    ...
}

要测试应用程序中的组件是否会返回预期的结果,请使用junit.Assert方法执行验证检查(或断言),以便将待测组件的状态与某个预期值进行比较。 为了使测试更具可读性,可以使用Hamcrest匹配器(如is()和equalTo()方法)将返回的结果与期望的结果进行匹配。

### Mock Android依赖

默认情况下,针对Gradle的Android插件将针对android.jar库的修改版本执行本地单元测试,该库不包含任何实际的代码。 相反,从你的单元测试方法调用Android类抛出一个异常。 这是为了确保只测试你的代码,而不依赖于Android平台的任何特定行为(你没有明确地mock)。

你可以使用mock框架在代码中删除外部依赖项,以便以预期的方式轻松测试组件与依赖项的交互。 通过用mock对象代替Android依赖关系,可以将单元测试与Android系统的其余部分分离,同时验证这些依赖关系中正确的方法被调用。Java的Mockito模拟框架(版本1.9.5及更高版本)提供了与Android单元测试的兼容性。借助Mockito可以配置模拟对象以在调用时返回某个特定的值。

要使用此框架将mock对象添加到本地单元测试中,请遵循以下编程模型:

1、在你的 build.gradle 文件中包含Mockito库依赖项,如设置上面的测试环境中所述。

2、在单元测试类定义的开始处,添加 @RunWith(MockitoJUnitRunner.class)注释。 这个注释告诉Mockito测试运行器验证你对框架的使用是否正确,并且简化了你的模拟对象的初始化。

3、要为Android依赖项创建一个模拟对象,请在字段声明之前添加@Mock注释。

4、为了Stub依赖的行为,可以通过使用when()return()方法来满足条件时,可以指定一个条件和返回值。

以下示例显示如何创建使用模拟Context对象的单元测试。

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.CoreMatchers.*;
import static org.mockito.Mockito.*;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import android.content.SharedPreferences; @RunWith(MockitoJUnitRunner.class)
public class UnitTestSample {     private static final String FAKE_STRING = "HELLO WORLD";     @Mock
    Context mMockContext;     @Test
    public void readStringFromContext_LocalizedString() {
        // Given a mocked Context injected into the object under test...
        when(mMockContext.getString(R.string.hello_word))
                .thenReturn(FAKE_STRING);
        ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);         // ...when the string is returned from the object under test...
        String result = myObjectUnderTest.getHelloWorldString();         // ...then the result should be the expected one.
        assertThat(result, is(FAKE_STRING));
    }
}

要了解有关使用Mockito框架的更多信息,请参阅示例代码中的Mockito API参考和SharedPreferencesHelperTest类。

### Error: "Method ... not mocked"

如果您运行测试,从Android SDK调用API,你不会使用mock,可能会收到一个错误,说这种方法没有被模拟。 这是因为用于运行单元测试的android.jar文件不包含任何当前代码(这些API仅由设备上的Android系统映像提供)。

相反,所有方法默认都会抛出异常。 这是为了确保你的单元测试你的代码,而不是依赖于Android平台的任何特定的行为(你没有明确地mock,如Mockito)。

如果抛出的异常说你的测试有问题,可以更改行为,以便通过在项目的顶级build.gradle文件中添加以下配置来返回null或零:

android {
  ...
  testOptions {
    unitTests.returnDefaultValues = true
  }
}

注意:将returnDefaultValues属性设置为true应该小心。 null / zero返回值可以在测试中引入回归,这些回调很难调试,并且可能允许失败的测试通过。只能用它作为最后的手段。

### 运行本地单元测试

要运行您的本地单元测试,请按照下列步骤操作:

1、通过单击工具栏中的“ Sync Project”,确保您的项目与Gradle同步。

2、以下列其中一种方式运行测试:

  • 要运行单个测试,请打开“Project”窗口,然后右键单击以进行测试,然后单击“Run”。
  • 要测试类中的所有方法,请右键单击测试文件中的类或方法,然后单击“Run”。
  • 要在目录中运行所有测试,请右键单击该目录并选择“Run Tests”。

Android测试(三):本地单元测试的更多相关文章

  1. 在Android Studio中进行单元测试和UI测试

    本篇教程翻译自Google I/O 2015中关于测试的codelab,掌握科学上网的同学请点击这里阅读:Unit and UI Testing in Android Studio.能力有限,如有翻译 ...

  2. 2、Android构建本地单元测试

    如果你的单元测试在Android中没有依赖或者只有简单的以来,你可以在你的本地开发环境中运行你的测试.这种测试比较高效因为它能让你避免将整个app安装到物理设备或虚拟机中执行单元测试.最后,执行单元测 ...

  3. Android测试(四):Instrumented 单元测试

    原文:https://developer.android.com/training/testing/unit-testing/instrumented-unit-tests.html Instrume ...

  4. Android测试提升效率批处理脚本(三)

    前言: 前面放出过几次批处理,这次只放一个环境检查的被管理员给打回来了,不得不再找找几个有含金量的放出来,请看正文~~~ 目录 1.Android环境检查 2.Android内存监控 3.模拟蓝牙手柄 ...

  5. Android测试基础题(三)

    今天接着给大家带来的是Android测试基础题(三).    需求:定义一个排序的方法,根据用户传入的double类型数组进行排序,并返回排序后的数组 俗话说的好:温故而知新,可以为师矣 packag ...

  6. Android APP压力测试(三)之Monkey日志自动分析脚本

    Android APP压力测试(三) 之Monkey日志自动分析脚本 前言 上次说要分享Monkey日志的分析脚本,这次贴出来分享一下,废话不多说,请看正文. [目录] 1.Monkey日志分析脚本 ...

  7. Android测试:从零开始2——local单元测试

    上一篇分析了android项目的测试分类,这一篇讲local单元测试. 参考android官方文档. 测试前需要配置测试环境,新建项目后,目录下会出现app/src/test/java/文件夹,这个文 ...

  8. Android测试:Fundamentals of Testing

    原文地址:https://developer.android.com/training/testing/fundamentals.html 用户在不同的级别上与你的应用产生交互.从按下按钮到将信息下载 ...

  9. Android测试(二):Android测试基础

    原文地址:https://developer.android.com/training/testing/fundamentals.html 用户在不同的级别上与你的应用产生交互.从按下按钮到将信息下载 ...

随机推荐

  1. yarn安装ant-报错

    异常现象: 使用react引用antd的库时报错 yarn add antd Trace: Error: connect ETIMEDOUT 114.55.80.225:80 at Object._e ...

  2. Android为TV端助力 遥控器的映射

    第一编写kl文件时先在盒子上输入getevent -v查看设备信息,设备信息里有vendor.product.version, 假如分别是xxxx,yyyy,zzzz,那么你的文件名就要命名为Vend ...

  3. 学习用Node.js和Elasticsearch构建搜索引擎(5):mac本机部署canal

    1.背景介绍 最近做的一个项目需要快速检索数据,经过商讨后采用了ElasticSearch作为快速检索数据引擎,但是数据如何同步到ES中是个问题,我们最开始计划了定时任务.mysql trigger等 ...

  4. SQL Server中通用数据库角色权限处理

    SQL Server中通用数据库角色权限处理   最近和同事在做数据库权限清理的事情,主要是删除一些账号:取消一些账号的较大的权限等,例如,有一些有db_owner权限,我们取消账号的数据库角色db_ ...

  5. mysql练习----More JOIN operations

    This tutorial introduces the notion of a join. The database consists of three tables movie , actor a ...

  6. SQL SERVER查询字段在哪个表里

    ); SET @ColumnName='字段名的模糊匹配'; SELECT 表名=D.NAME, 表说明 THEN ISNULL(F.VALUE, ' ') ELSE ' ' END, 字段序号 = ...

  7. C# DBHelper类 参考

    using System;using System.Collections.Generic;using System.Text;using System.Configuration;using Sys ...

  8. Django的安装和启动

    花了将近半个月的时间终于完成了Django的初步学习,从安装到实践MVTC架构,再到写简易的model和view,踩过不少坑,因此这里分享出来,也算一个阶段性的总结. 1.安装Django pip i ...

  9. ASP.NET中的参数与特殊类型和特性

    一.可选参数和命名参数        1.可选参数            语法:                [修饰符] 返回类型 方法名(必选参数1...必选参数n,可选参数1...可选参数n)  ...

  10. Python的变量以及类型

    1.程序是用来处理数据的,变量就是用来存储数据的  num1 = 100 2.为了更充分的利用内存空间以及更有效率的管理内存,变量是有不同的类型 3.怎样知道一个变量的类型呢? 3.1 在python ...