原文:https://developer.android.com/training/testing/unit-testing/local-unit-tests.htmlhtml
若是你的单元测试没有依赖或者只有简单的Android依赖,则应该在本地开发机器上运行测试。这种测试方法很是高效,由于它能够帮助你避免每次运行测试时将目标应用程序和单元测试代码加载到真机或模拟器上的开销。所以,运行单元测试的执行时间大大减小了。经过这种方法,你一般使用mock框架(如Mockito)来完成任何依赖关系。java
在你的Android Studio项目中,必须将本地单元测试的源文件存储在module-name/src/test/java/ 目录中。在建立新项目时,该目录已经存在。android
你还须要配置项目的测试依赖,以使用JUnit 4框架提供的标准API。若是你的测试须要与Android依赖关系进行交互,请包含Mockito库以简化本地单元测试。要了解有关在本地单元测试中使用模拟对象的更多信息,请参阅模拟Android依赖关系。git
在你的App程序的目录下找到build.gradle文件中,将这些库指定为依赖项:github
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()方法)将返回的结果与指望的结果进行匹配。单元测试
默认状况下,针对Gradle的Android插件将针对android.jar库的修改版本执行本地单元测试,该库不包含任何实际的代码。 相反,从你的单元测试方法调用Android类抛出一个异常。 这是为了确保只测试你的代码,而不依赖于Android平台的任何特定行为(你没有明确地mock)。测试
你可使用mock框架在代码中删除外部依赖项,以便以预期的方式轻松测试组件与依赖项的交互。 经过用mock对象代替Android依赖关系,能够将单元测试与Android系统的其他部分分离,同时验证这些依赖关系中正确的方法被调用。Java的Mockito模拟框架(版本1.9.5及更高版本)提供了与Android单元测试的兼容性。借助Mockito能够配置模拟对象以在调用时返回某个特定的值。
要使用此框架将mock对象添加到本地单元测试中,请遵循如下编程模型:
一、在你的 build.gradle 文件中包含Mockito库依赖项,如设置上面的测试环境中所述。
二、在单元测试类定义的开始处,添加 @RunWith(MockitoJUnitRunner.class)
注释。 这个注释告诉Mockito测试运行器验证你对框架的使用是否正确,而且简化了你的模拟对象的初始化。
三、要为Android依赖项建立一个模拟对象,请在字段声明以前添加@Mock注释。
四、为了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类。
若是您运行测试,从Android SDK调用API,你不会使用mock,可能会收到一个错误,说这种方法没有被模拟。 这是由于用于运行单元测试的android.jar文件不包含任何当前代码(这些API仅由设备上的Android系统映像提供)。
相反,全部方法默认都会抛出异常。 这是为了确保你的单元测试你的代码,而不是依赖于Android平台的任何特定的行为(你没有明确地mock,如Mockito)。
若是抛出的异常说你的测试有问题,能够更改行为,以便经过在项目的顶级build.gradle文件中添加如下配置来返回null或零:
android { ... testOptions { unitTests.returnDefaultValues = true } }
注意:将returnDefaultValues属性设置为true应该当心。 null / zero返回值能够在测试中引入回归,这些回调很难调试,而且可能容许失败的测试经过。只能用它做为最后的手段。
要运行您的本地单元测试,请按照下列步骤操做:
一、经过单击工具栏中的“ Sync Project”,确保您的项目与Gradle同步。
二、如下列其中一种方式运行测试: