目录标题
概述
Android的单元測试能够分为两部分:
- Local unit tests:执行于本地JVM
- Instrumented test:执行于真机或者模拟器
假设使用Local測试,须要保证測试过程中不会调用Android系统API。否则会抛出RuntimeException异常,由于Local測试是直接跑在本机JVM的,而之所以我们能使用Android系统API,是由于编译的时候,我们依赖了一个名为“android.jar”的jar包,可是jar包里全部方法都是直接抛出了一个RuntimeException。是没有不论什么不论什么实现的。这仅仅是Android为了我们能通过编译提供的一个Stub!当APP执行在真实的Android系统的时候,由于类载入机制,会载入位于framework的具有真正实现的类。
由于我们的Local是直接在PC上执行的。所以调用这些系统API便会出错。
那么问题来了,我们既要使用Local測试,但測试过程又难免遇到调用系统API那怎么办?其中一个方法就是mock objects。比方借助Mockito,第二种方式就是使用Robolectric。 Robolectric就是为解决问题而生的。它实现一套JVM能执行的Android代码。然后在unit test执行的时候去截取android相关的代码调用。然后转到他们的他们实现的Shadow代码去执行这个调用的过程
怎样使用
为项目加入依赖:
android {
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
dependencies {
testImplementation 'org.robolectric:robolectric:4.2'
}
指定RobolectricTestRunner为执行器
为測试用例加入注解,指定測试执行器为RobolectricTestRunner。注意。这里要通过Config指定constants = BuildConfig.class,Robolectric 会通过constants推导出输出路径。假设不进行配置。Robolectric可能不能找到你的manifest、resources和assets资源
@RunWith(RobolectricTestRunner.class)
@Config(constants = BuildConfig.class)
public class MainActivityTest {
}
什么是Shadow类
Shadow是Robolectric的立足之本,如其名,作为影子。一定是变幻莫測,时有时无,且依存于本尊。Robolectric定义了大量模拟Android系统类行为的Shadow类,当这些系统类被创建的时候,Robolectric会查找相应的Shadow类并创建一个Shadow类与原始类关联。每当系统类的方法被调用的时候,Robolectric会保证Shadow相应的方法会调用。这些Shadow对象,丰富了本尊的行为,能更方便的对Android相关的对象进行測试。
比方,我们能够借助ShadowActivity验证页面是否正确跳转了
/**
* 验证点击事件是否触发了页面跳转。验证目标页面是否预期页面
*
* @throws Exception
*/
@Test
public void testJump() throws Exception {
// 默认会调用Activity的生命周期: onCreate->onStart->onResume
MainActivity activity = Robolectric.setupActivity(MainActivity.class);
// 触发button点击
activity.findViewById(R.id.activity_main_jump).performClick();
// 获取相应的Shadow类
ShadowActivity shadowActivity = Shadows.shadowOf(activity);
// 借助Shadow类获取启动下一Activity的Intent
Intent nextIntent = shadowActivity.getNextStartedActivity();
// 校验Intent的正确性
assertEquals(nextIntent.getComponent().getClassName(), SecondActivity.class.getName());
}
@Config配置
能够通过@Config定制Robolectric的执行时的行为。
这个注解能够用来凝视类和方法,假设类和方法同一时候使用了@Config,那么方法的设置会覆盖类的设置。
你能够创建一个基类。用@Config配置測试參数。这样,其它測试用例就能够共享这个配置了
配置SDK版本号
Robolectric会依据manifest文件配置的targetSdkVersion选择执行測试代码的SDK版本号。假设你想指定sdk来执行測试用例。能够通过以下的方式配置
@Config(sdk = Build.VERSION_CODES.JELLY_BEAN)
public class SandwichTest {
@Config(sdk = Build.VERSION_CODES.KITKAT)
public void getSandwich_shouldReturnHamSandwich() {
}
}
配置Application类
Robolectric会依据manifest文件配置的Application配置去实例化一个Application类,假设你想在測试用例中又一次指定,能够通过以下的方式配置
@Config(application = CustomApplication.class)
public class SandwichTest {
@Config(application = CustomApplicationOverride.class)
public void getSandwich_shouldReturnHamSandwich() {
}
}
指定Resource路径
Robolectric能够让你配置manifest、resource和assets路径,能够通过以下的方式配置
@Config(manifest = "some/build/path/AndroidManifest.xml",
assetDir = "some/build/path/assetDir",
resourceDir = "some/build/path/resourceDir")
public class SandwichTest {
@Config(manifest = "other/build/path/AndroidManifest.xml")
public void getSandwich_shouldReturnHamSandwich() {
}
}