- 构建本地单元测试
- 设置你的测试环境
- 创建本地单元测试类
- 模仿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,你能够配置模仿对象,当调用的时候能够返回一些特定值。
为了添加一个模仿对象到使用这个框架的本地单元测试,参照这个编程模型。
- 在 build.gradle 文件中引入Mockito库依赖。
- 在单元测试类定义开始处,添加注释@RunWith(MockitoJUnitRunner.class) ,这个注释告知Mockito test runner 你的框架使用是正确的,并且简化模仿对象的初始化。
- 为了给一个Android 依赖创建模仿对象,在域声明之前添加 @Mock 注释
- 为了摒除依赖的行为,你可以通过方法 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,并且可能通过失败的测试。把它作为最后的手段。
运行本地单元测试
运行本地单元测试,遵循以下步骤。
- 点击工具栏的Sync Project 确保你的工程和gradle同步。
- 用如下方法之一运行单元测试。
- 运行单一测试,打开Project窗口,然后右键点击一个测试并且点击Run 。
- 测试一个类中的所有方法,右键点击一个类或者测试文件中的方法,然后点击Run
- 运行一个路径的所有测试,右键点击路径,然后选择Run Tests
Android的gradle插件编译位于默认路径(src/test/java/)下的本地单元测试代码,构建一个测试App,然后用默认的test runner 类本地执行。Android Studio 之后在Run 窗口显示结果。