如果你的单元测试没有依赖或者只有Android上的简单依赖,你应该在本地开发机器上运行测试。 这种测试方法是高效的,因为它可以帮助您避免每次运行测试时将目标应用程序和单元测试代码加载到物理设备或模拟器上的开销。 因此,运行单元测试的执行时间大大减少。 使用这种方法,通常使用模拟框架(如Mockito)来实现任何依赖关系。
设置测试环境
在您的Android Studio项目中,必须将用于本地单元测试的源文件存储在module-name/src/test/java/
。 创建新项目时,此目录已存在。
您还需要为项目配置测试依赖关系,以使用JUnit 4框架提供的标准API。 如果您的测试需要与Android依赖关系交互,请包括Mockito库以简化本地单元测试。 要了解有关在本地单元测试中使用模拟对象的更多信息,请参阅模拟Android依赖。
在应用程序的顶级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));
}
...
}
package com.le.bbs;
import com.le.bbs.api.RequestInterceptor;
import org.junit.Assert;
import org.junit.Test;
/**
* To work on unit tests, switch the Test Artifact in the Build Variants view.
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
String query = "sso_tk=&appKey=lemeapp&timeStamp=1471516952";
Assert.assertEquals(RequestInterceptor.generateSign(query), "35083f2dbece");
}
}
验证通过 Process finished with exit code 0
验证不通过
org.junit.ComparisonFailure:
Expected :35083f2dbece
Actual :35083f2dbece3
要测试应用程序中的组件是否返回预期结果,请使用junit.Assert方法执行验证检查(或断言),以便将受测试组件的状态与某些预期值进行比较。 为了使测试更可读,可以使用Hamcrest matchers(例如is() 和equalTo() 方法)将返回的结果与预期结果进行匹配。
模拟Android依赖
默认情况下,Android的插件Gradle针对android.jar库的修改版本执行您的本地单元测试,该版本不包含任何实际代码。 相反,从单元测试中调用Android类的方法会抛出异常。 这是为了确保只测试你的代码,不依赖于Android平台的任何特定的行为(你没有明确的模拟)。
您可以使用模拟框架在代码中消除外部依赖关系,以便轻松测试您的组件是否达到预期。 通过用模拟对象替换Android依赖项,您可以将单元测试与Android系统的其余部分隔离,同时验证这些依赖关系中的方法是否被正确调用。 Java的Mockito 模拟框架(1.9.5及更高版本)提供了与Android单元测试的兼容性。 使用Mockito,您可以配置模拟对象以便在调用时返回一些特定值。
要使用此框架需要将模拟对象添加到本地单元测试,请遵循以下编程模型:
- 在build.gradle文件中包含Mockito库依赖关系,如文章上面的设置测试环境所述。
- 在单元测试类定义的开始,添加
@RunWith(MockitoJUnitRunner.class)
注释。 这个注释告诉Mockito测试运行器验证框架使用的正确性,并简化了你的模拟对象的初始化。 - 要为Android依赖项创建模拟对象,请在字段声明之前添加@Mock注释。
- 要消除依赖关系的行为,可以使用when()和thenReturn()方法指定条件并返回值。
以下示例显示如何创建使用mock上下文对象的单元测试。
package com.le.bbs;
import android.content.Context;
import com.le.bbs.test.ClassUnderTest;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.mockito.Mockito.*;
/**
* @author Sayangnala
* @ClassName: UnitTestSample
* @Description: 单元测试样例(来源于官方文档)
* @date 2016/10/13 10:09
*/
@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...
//org.mockito.Mockito.when
when(mMockContext.getString(R.string.app_name)).thenReturn(FAKE_STRING);
ClassUnderTest myObjectUnderTest = new ClassUnderTest(mMockContext);
String result = myObjectUnderTest.getHelloWorldString();
//..then the result should be the expected one.
//org.hamcrest.MatcherAssert.assertThat
//org.hamcrest.CoreMatchers.is
assertThat(result, is(FAKE_STRING));
}
}
要测试的类:ClassUnderTest.java
package com.le.bbs.test;
import android.content.Context;
import com.le.bbs.R;
/**
* @author yuhushuan
* @ClassName: ClassUnderTest
* @Description: 配合单元测试类
* @date 2016/10/13 10:32
*/
public class ClassUnderTest {
Context mContext;
public ClassUnderTest(Context context) {
mContext = context;
}
public String getHelloWorldString() {
return mContext.getString(R.string.app_name);
}
}
要了解有关使用Mockito框架的更多信息,请参阅示例代码中的Mockito API参考和sample code 的SharedPreferencesHelperTest类。
如果测试代码抛出Android.jar中Android API的异常,您可以通过项目的顶级build.gradle文件中添加以下配置来替换返回null或0:
android {
...
testOptions {
unitTests.returnDefaultValues = true
}
}
警告:将returnDefaultValues属性设置为true应该小心。 零/零返回值可以在测试中引入回归,这难以调试,并且可能允许失败的测试通过。 只能使用它作为最后的手段。
运行本地单元测试
按照下列步骤运行本地单元测试:
1. 通过单击工具栏中的同步项目,确保您的项目与Gradle同步。
2. 使用以下方法之一运行测试:
- 要运行单个测试,请打开“Project”窗口,然后右键单击测试,然后单击Run 。
- 要测试类中的所有方法,请右键单击测试文件中的类或方法,然后单击Run 。
- 要在目录中运行所有测试,请右键单击目录并选择 Run tests。
Gradle的Android插件编译位于默认目录(src/test/java/
)中的本地单元测试代码,构建一个测试应用程序,并使用默认的测试运行器类在本地执行它。 然后,Android Studio将在“运行”窗口中显示结果。