现在前面
你应该编写并使用测试,作为android应用开发环节的一部分,好的测试能帮助我们在开发过程中早一些捕捉到bugs,并且树立你信心。
为了核实app中的特殊行为,检验在不同android设置中的兼容性,你可以写一个test case.本文将教你如何使用google提供的JUnit 4框架、测试APIs和工具创建一个test case,以及如何运行测试。
如果你的单元测试没有依赖,或者仅仅是简单的Android依赖,你应该在本地开发机器上运行你的测试。这种测试方法很有效率,因为它可以帮你在每次运行测试时避免加载目标应用的开支,以及避免测试代码映射到Android设备上。因此,单元测试的运行时间会大幅减少。用这种方式,你通常需要使用mock框架,像Mockito,来满足一些依赖关系。
配置测试环境
在你的AS项目中,你应该把单元测试文件放到module-mane/src/test/java.目录下。这一个目录在你创建一个新项目时就已经存在了。不同风味(Flavor)的测试文件应放在相应风味的单元测试目录下,如图:
你还需要配置测试依赖到你的项目上,使用JUnit 4 框架提供的标准APIs。如果你的测试需要与Android依赖交互,引入Mockito库简化本地单元测试。想学习更多mock用法,下面会提到
在build.gradle中添加必要的依赖库:
dependencies {
// Required – JUnit 4 framework
testCompile ‘junit:junit:4.12’
// Optional – Mockito framework
testCompile ‘org.mockito:mockito-core:1.10.19’
}
创建本地测试类
你的本地单元测试应该按照JUnit4测试类的方式来写。JUnit是最流行的、最广泛的java单元测试框架。最新版本的框架让你的测试写得更简洁更灵活。不像以前的基于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方法来执行校验检查(或assertions),比较在测试下的组件的状态对一些预期的值。让测试更加易读,你可以使用Hamcrest matchers(例如is()、equalTo()方法)来匹配返回结果与预期值,需要引入Hamcrest依赖。
Mock Android依赖
默认的,Android插件gradle执行本地单元测试依靠一个修改版的android.jar库,不包含任何实际代码。相反,本地测试的方法调用Android的类会抛异常。
你可以使用mocking框架来根存代码中的外部依赖,容易地在预期的方式里对有依赖的组件交互进行测试。通过mock对象取代Android依赖,你能把单元测试从其余的Android系统脱离出来。Java的Mockito模拟框架(版本1.9.5或更高)兼容Android单元测试。用Mockito,当调用时,你能设置对象返回一些特定值。
用这个框架往单元测试测试中添加mock对象,参照下面的编程模型:
1. 在build.gradle文件中引入Mockito库的依赖。
2. 在开始定义单元测试类时,在类名行添加RunWith(MockitoJUnitRunner.class) 注解。这个注解告诉Mockito测试运行器验证你使用的框架的正确性,并简化mock对象的初始化。
3. 为创建Android依赖mock对象,在字段声明前添加@mock注解。
4. 为了根存依赖的行为,你可以指定一个条件和返回值,当使用when()和thenReturn()方法满足条件时。
下面的实例展示如何创建一个用mock 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,以及sample code中的 SharedPreferencesHelperTest 类。
运行本地单元测试
- 确认你的项目已经同步,点击Sync Project 工具栏按钮进行同步。
- 运行测试可以通过以下几种方式:
运行一个测试文件,单开项目窗体,右键点击一个测试,选择Run
测试一个类中的所有测试方法,右键点击这个测试文件中的一个类或一个方法,选择Run
运行目录下的所有测试,右键点击这个目录,并选择Run tests。
Android插件Gradle编译位于默认目录(src/test/java/.)下的本地单元测试,构建测试app,以及执行它本地使用的默认测试器的类。在AS的Run窗体中显示结果。