单元测试是最基本的测试。
Android单元测试分为本地级单元测试、仪器级单元测试:
1. 本地级单元测试,是在开发环境中进行的测试,不需要Android设备(模拟器或者真实的);
2. 仪器级单元测试,是在Android(真实或模拟的)设备上运行的测试。
本地级单元测试
本节介绍Android的本地级单元测试。
建立测试环境
为了确保本地级单元测试可以运行,通常需要在模块(通常是app模块)的gradle.build文件配置两个库依赖:JUnit4、Mockito。
dependencies {
...
// Required -- JUnit 4 framework
testCompile 'junit:junit:4.12'
// Optional -- Mockito framework
testCompile 'org.mockito:mockito-core:1.10.19'
}
JUnit4是最基本的必须的本地级单元测试框架,必须要配置。Mockito是可选的,当测试需要模拟与Android Dependencies交互时,则需要配置Mockito。
创建并运行本地级单元测试
在“src\test\java\包名\”目录下创建一个普通的Java类,然后在该Java类中定义一个public、返回值为void的方法,最好让该方法抛出一个异常,最后使用“@Test”注解该方法。
“src\test\java\包名\”目录示例
package com.trb.unittestdemo;
import org.junit.Test;
import static org.junit.Assert.*;
public class ExampleUnitTest {
@Test
public void addition_isCorrect() throws Exception {
System.out.println("Test Start");
assertEquals(4, 2 + 2);
System.out.println("Test Over");
}
}
本地级单元测试示例代码
运行本地级单元测试的方法有三种:
1. 运行单元测试的单个方法,选中该方法,然后右键选择Run”方法名”;
2. 运行单元测试的所有方法,选中该测试类,然后右键选择Run”测试类名”;
3. 运行单元测试包中所有的测试类,选中该包,然后右键选择Run’Tests in “包名”’。
本地级单元测试的运行结果示例
模拟(Mock)Android Dependencies
本地级单元测试只能运行标准Java库,如果你的测试要依赖Android库,那么就需要使用Mockito库来mock Android dependencies。
编写mock unit test,除了要遵守本地级单元测试类的编写规则,还必须要实现以下几点:
1.使用“@RunWith(JunitRunner.class)”注解该类;
2.对Android dependencies的对象使用“@Mock”进行注解;
3.构建一个普通的Java类来模拟Android dependencies的对象。
package com.trb.unittestdemo;
import android.content.Context;
public class MockTestObject {
private Context mockContext;
public MockTestObject(Context mockContext) {
this.mockContext = mockContext;
}
public String getText() {
return mockContext.getString(R.string.app_name);
}
}
模拟Android dependencies的普通Java类
package com.trb.unittestdemo;
import android.content.Context;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.runners.MockitoJUnitRunner;
import static java.lang.System.out;
import static org.mockito.Mockito.when;
@RunWith(MockitoJUnitRunner.class)
public class SMathUnitTest {
private static final String FAKE_STRING = "FAKE_STRING";
@Mock
private Context mockContext;
@Test
public void mockTestDemo() throws Exception {
when(mockContext.getString(R.string.app_name)).thenReturn(FAKE_STRING);
MockTestObject mockTestObject = new MockTestObject(mockContext);
out.println("mockTestDemo >>> " + mockTestObject.getText());
}
}
Mock unit test的类
运行结果示例
在该例中,mockTestObject.getText()方法的返回结果永远是字符常量FAKE_STRING所定义的值。
注意:
运行Mock测试时,如果发现了Error:… not mocked错误时,这表示需要在模块的build.gradle文件中配置
android {
...
testOptions {
unitTests.returnDefaultValues = true
}
}
仪器级单元测试
本地级单元测试是运行在开发机上的,只能使用JVM所提供的API,或者使用Mockito模拟Android库。这对于要运行实际的Android库的测试的作用是非常有限的,仪器级单元测试就是解决这个问题。
仪器级单元测试要求必须运行在Android(真实或模拟的)设备上,调用Android设备上的Android库来支持测试。在这里要指出的是,Android设备上并不会出现App的UI界面。
建立测试环境
在模块的build.gradle文件中配置
android {
...
defaultConfig {
...
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
dependencies {
...
androidTestCompile 'com.android.support:support-annotations:26.1.0'
androidTestCompile 'com.android.support.test:runner:1.0.1'
androidTestCompile 'com.android.support.test:rules:1.0.1'
}
执行仪器级单元测试
编写仪器级单元测试,须要遵守以下几点:
1. 使用“@RunWith(AndroidJUnit4.class)”注解测试类;
2. 使用“@Test”注解测试方法。
仪器级单元测试的运行方法与本地级单元测试类似,不过必须要先连接上Android设备。
package com.trb.unittestdemo;
import android.content.Context;
import android.support.test.InstrumentationRegistry;
import android.support.test.runner.AndroidJUnit4;
import android.util.Log;
import org.junit.Test;
import org.junit.runner.RunWith;
import static org.junit.Assert.*;
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Test
public void useAppContext() throws Exception {
Log.w(getClass().getName(), "useAppContext: ");
// Context of the app under test.
Context appContext = InstrumentationRegistry.getTargetContext();
assertEquals("com.trb.unittestdemo", appContext.getPackageName());
}
}
仪器级单元测试的示例
仪器级单元测试的运行结果的示例
仪器级单元测试的运行Log信息的示例