• 构建本地单元测试
  • 设置你的测试环境
  • 创建本地单元测试类
  • 模仿Android依赖Mock Android Dependency
  • 运行本地单元测试


构建本地单元测试

如果你的单元测试没有依赖或者仅仅有简单的Android依赖,你应当在本地开发器上运行你的测试。这种测试方法很高效,因为它让你避免每次运行测试时加载目标App和测试代码到一个物理设备或者模拟器上的时间开销。结果是运行你的单元测试的时间极大减少。这种测试方法,你通常使用一个模仿框架,比如Mockito,来实现任何依赖关系。

设置你的测试环境

在你的AndroidStudio工程中,你必须存储本地单元测试的源文件在路径module-name/src/test/java/下。在你创建新的工程师该路径已经存在。

你还需要为你的工程配置测试依赖(dependencies),以使用JUnit4框架提供的标准API。如果你的测试需要和Android依赖交互,导入Mockito库以简化本地单元测试。学习更多关于你的本地单元测试中的模仿对象,请查看下文Mocking Android dependencies(模仿安卓依赖)。

在你的App的最高层级的 build.gradle 文件内,你需要指定这些库作为依赖 (注:代码片段中的版本号请以最新版本号为准)

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

创建本地单元测试类

你的本地单元测试类应当写成JUnit4测试类。对Java来讲,JUnit是最流行、使用最广泛的测试框架。该框架的最新版本,JUnit4,与其之前的版本比较,是你能够以更简洁、更灵活的方式编写测试。不像基于JUnit3的Android单元测试的方法,使用JUnit4,你无需继承类junit.framework.TestCase。你也无需给你的测试方法名加前缀test,或者使用包junit.framework 和包 junit.extensions 中的任何类。

为创建一个基本的JUnit4测试类,需创建一个包含一个或者多个测试方法的JAVA类。一个测试方法以注释@Test 开始,此外包含你所测试组件的单一功能的执行与验证代码。

以下示例展示了你如何实现本地单元测试类。测试方法emailValidator_CorrectEmailSimple_ReturnsTrue 验证测试的app中的方法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));
    }
    ...
}

为了测试App中的组件返回期望的结果,使用 junit.Assert 的执行验证检查的方法,来比较测试组件的状态和期望的结果。为了使测试更加可读,你可以使用 Hamcrest matchers(比如is()equalTo())来匹配返回的结果与预期的结果

模仿Android依赖(Mock Android Dependency)

默认情况下, Android Plug-in for Gradle (Android的gradle插件) 对不含任何实际代码的android.jar 库的一个修改版本执行本地单元测试。结果,单元测试中调用Android类的方法抛出异常。这保证了你仅仅测试你的代码,不依赖Android平台的任何特定行为。

你可以使用一个模仿框架来摒除你代码中的外部依赖,以方便的测试你的组件和依赖以一种预期的方式交互。通过用模仿对象替换Andorid依赖,在保证依赖中的正确方法被调用的情况下,你能够把单元测试和Android系统的剩余部分隔离。Java版本的Mockito 模仿框架(1.9.5版本及更高)提供了与Android单元测试的兼容性。使用Mockito,你能够配置模仿对象,当调用的时候能够返回一些特定值。

为了添加一个模仿对象到使用这个框架的本地单元测试,参照这个编程模型。

  1. build.gradle 文件中引入Mockito库依赖。
  2. 在单元测试类定义开始处,添加注释@RunWith(MockitoJUnitRunner.class) ,这个注释告知Mockito test runner 你的框架使用是正确的,并且简化模仿对象的初始化。
  3. 为了给一个Android 依赖创建模仿对象,在域声明之前添加 @Mock 注释
  4. 为了摒除依赖的行为,你可以通过方法 when()thenReturn() 指定一个条件并且当条件满足的情况下返回结果。

如下示例展示了如何创建使用了模仿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 reference示例代码中的SharedPreferencesHelperTest 类。

如果 android.jar 中的Android API抛出的异常对你的测试是有问题的,你可以在你的工程的最高层级 build.gradle 文件中添加如下配置来改变行为以使方法返回null或者0 。

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

注意:设定returnDefaultValues 的属性为true需要谨慎操作。null/0 的返回值能够在你的测试中引入回归,这很难debug,并且可能通过失败的测试。把它作为最后的手段。

运行本地单元测试

运行本地单元测试,遵循以下步骤。

  1. 点击工具栏的Sync Project 确保你的工程和gradle同步。
  2. 用如下方法之一运行单元测试。
  • 运行单一测试,打开Project窗口,然后右键点击一个测试并且点击Run
  • 测试一个类中的所有方法,右键点击一个类或者测试文件中的方法,然后点击Run
  • 运行一个路径的所有测试,右键点击路径,然后选择Run Tests

Android的gradle插件编译位于默认路径(src/test/java/)下的本地单元测试代码,构建一个测试App,然后用默认的test runner 类本地执行。Android Studio 之后在Run 窗口显示结果。