单元测试
category
测试
date
Apr 10, 2026
icon
password
slug
unitTest
status
Published
summary
单元测试相关知识
tags
type
Post
1、kotlin
2、Mockito 基础及使用
1. 什么是单元测试
2. 介绍Mockito的由来
Mockito是由Szczepan Faber在2008年创建的一个Java测试框架,用于简化测试中的模拟(Mocking)过程。它基于EasyMock的理念,致力于提供一种更简单、更直观的方式来编写和管理测试代码。Mockito允许开发者创建和配置模拟对象,以便隔离单元测试中的依赖,专注于测试逻辑的核心部分。
3. 为什么要使用Mockito,解决哪些测试痛点
4. 哪些地方可以使用,以及如何使用
Mockito可以用于任何涉及到对象依赖的单元测试场景,特别适合以下情况:
● 测试需要依赖多个其他对象的类。
● 测试依赖外部资源的类(如数据库、Web服务)。
● 测试复杂的对象交互。
依赖配置
● mockito-core: 用于 本地单元测试,其测试代码路径位于 module-name/src/test/java/
● mockito-android: 用于 设备测试,即需要运行 android 设备进行测试,其测试代码路径位于 module-name/src/androidTest/java/
5. 相关概念
● Mock 对象
mock对象的概念就是我们想要创建一个可以替代实际对象的对象,这个模拟对象要可以通过特定参数调用特定的方法,并且能返回预期结果。
● Stub(桩)
桩指的是用来替换具体功能的程序段。桩程序可以用来模拟已有程序的行为或是对未完成开发程序的一种临时替代。
● 设置预期
通过设置预期明确 Mock对象执行时会发生什么:
比如返回特定的值、抛出一个异常、触发一个事件等,又或者调用一定的次数
● 验证预期的结果
设置预期和验证预期是同时进行的。设置预期在调用测试类的函数之前完成,验证预期则在它之后。
所以,首先你设定好预期结果,然后去验证你的预期结果是否正确
6. 关键字介绍
7. 验证方法调用的关键字:verify
用法
verify用于验证模拟对象的方法是否按预期被调用。它可以检查方法的调用次数、调用顺序、参数等。
关键方法
● verify(T mock): 验证方法是否被调用。
● times(int wantedNumberOfInvocations): 验证方法被调用的次数。
● never(): 验证方法从未被调用。
● atLeast(int minNumberOfInvocations): 验证方法至少被调用的次数。
● atMost(int maxNumberOfInvocations): 验证方法最多被调用的次数。
● inOrder(T... mocks): 验证方法的调用顺序。
其他用法
你还可以使用argumentCaptor捕获参数,验证方法调用时传递的参数。
8. 主要API使用
创建Mock对象
定义行为
验证行为
其他API
● 捕获参数:ArgumentCaptor<T> captor = ArgumentCaptor.forClass(Class<T>)
● 部分模拟:Spy<T> spy(T object)
● 序列化:Serialized<T> serialized = Serialized<T>(T object)
示例代码
Mockito Spy
在Mockito中,Spy用于部分模拟对象。与Mock对象不同,Spy对象是一个真实对象的代理,它允许你监控对象的行为,并在必要时改变其行为。Spy对象可以调用真实对象的方法,同时也可以模拟部分方法的行为。
主要特点
● 真实方法调用:默认情况下,Spy对象会调用真实对象的方法。
● 部分模拟:可以选择性地模拟对象的方法,而不是完全替换。
● 监控行为:可以验证方法调用和参数。
使用场景
Spy通常用于以下场景:
● 需要测试对象的部分行为,但又需要调用其真实方法。
● 需要监控对象的方法调用,但不希望完全模拟整个对象。
示例代码
假设我们有一个简单的类Calculator,我们希望测试其中的部分方法,同时调用其他方法的真实实现。
创建Calculator类
使用Spy进行测试
我们希望在测试中调用add方法的真实实现,但模拟subtract方法的行为。
详细说明
创建Spy对象:通过@Spy注解或Mockito.spy()方法创建Spy对象。在这里,我们使用注解方式。
初始化Spy对象:使用MockitoAnnotations.initMocks(this)方法初始化注解。
调用真实方法:调用Spy对象的add方法,该方法会调用真实的实现。
调用并验证模拟方法:调用subtract方法并验证返回值,同时验证方法的调用情况。
通过使用Spy,你可以在不完全模拟整个对象的情况下,部分控制对象的行为,这在某些测试场景中非常有用。
google demo
Mockito官方demo
3、Robolectric 基础与使用
1. robolectric是什么?
官方原文:
Robolectric is the industry-standard unit testing framework for Android. With Robolectric, your tests run in a simulated Android environment inside a JVM, without the overhead and flakiness of an emulator. Robolectric tests routinely run 10x faster than those on cold-started emulators.
Robolectric supports running unit tests for 14 different versions of Android, ranging from Lollipop (API level 21) to U (API level 34).
译:
Robolectric 是 Android 的行业标准单元测试框架。借助 Robolectric,您的测试可以在 JVM 内的模拟 Android 环境中运行,而无需模拟器的开销和不稳定。 Robolectric 测试的运行速度通常比冷启动模拟器上的测试快 10 倍。
2. Robolectric能帮助解决什么问题?
测试Android代码逻辑,光有JUnit和Mockito是不够的,假设你使用了TextView的setText,用Mockito框架的话,默认的TextView的getText方法会返回null,如果是简单的代码,使用Mockito的桩设置还可以接受,如果是要测试到Activity的生命周期等一些复杂逻辑就显得比较复杂了。
为了解决这个问题,诞生了Instrumentation、Robolectric等等的测试框架,不过Instrumentation实际上还是要运行代码到平台上测试,耗费大量的时间,介绍的是运行在JVM上的Robolectric测试框架。
3. Robolectric基本原理
在使用Robolectric之前我们先要明白Robolectric是如何工作的。比如说我们前文说到的TextView,如果我们使用Mockito,他给我们提供的是Mock后的TextView,而Robolectric给我们提供的是ShadowTextView,这个ShadowTextView实现了TextView身上的方法,但他又与Android的运行环境无关,也就是说他可以像使用TextView一样的方法,但不用在平台上运行代码,大大提高测试效率。
4. 我们为什么需要使用Robolectric?
为解决在JVM中能正常使用Android Context及其支持的API,如获取app的真实渠道名,获取app需要加载的资源文件,如assert目录下的资源图,或者文件,以及被测试类可能依赖Context进行其他接口调用或者参数传递。
5. 什么是Android Context?为什么必须使用它呢?
我们最常用的Activity,Service,Application都是Context的子类。所以知道Context的具体实现是非常有必要的。
下面是Context的体系结构图:
Context是Android App程序的基础,可以看作java 的 man()函数一样的重要,Android很多的API,功能都是需要在Context初始化后才能进行的。
6. 怎么配置使用呢?
7. 配置SDK版本
Robolectric会根据manifest文件配置的targetSdkVersion选择运行测试代码的SDK版本,如果你想指定sdk来运行测试用例,可以通过下面的方式配置
8. 配置Application类
Robolectric会根据manifest文件配置的Application配置去实例化一个Application类,如果你想在测试用例中重新指定,可以通过下面的方式配置
9. 驱动Activity生命周期
利用ActivityController我们可以让Activity执行相应的生命周期方法,如
UI组件状态
10. 其他支持
Fragment的测试
BroadcastReceiver的测试
Service的测试
11. 什么是Shadow类
Shadow是Robolectric的立足之本,如其名,作为影子,一定是变幻莫测,时有时无,且依存于本尊。Robolectric定义了大量模拟Android系统类行为的Shadow类,当这些系统类被创建的时候,Robolectric会查找对应的Shadow类并创建一个Shadow类与原始类关联。每当系统类的方法被调用的时候,Robolectric会保证Shadow对应的方法会调用。这些Shadow对象,丰富了本尊的行为,能更方便的对Android相关的对象进行测试。
比如,我们可以借助ShadowActivity验证页面是否正确跳转了
12. 如何自定义Shadow对象
首先,创建原始对象Person
其次,创建Person的Shadow对象
接下来,需自定义TestRunner,添加Person对象为要进行Shadow的对象
最后,在测试用例中,ShadowPerson对象将自动代替原始对象,调用Shadow对象的数据和行为
13. 追加模块
为了减少依赖包的大小,Robolectric的shadows类成了好几部分:
SDK Package | Robolectric Add-On Package |
com.android.support.support-v4 | org.robolectric:shadows-support-v4 |
com.android.support.multidex | org.robolectric:shadows-multidex |
com.google.android.gms:play-services | org.robolectric:shadows-play-services |
com.google.android.maps:maps | org.robolectric:shadows-maps |
org.apache.httpcomponents:httpclient | org.robolectric:shadows-httpclient |
其他
Android单元测试学习资料
● Android官方文档,目前我们主要采用本地化测试方案
● Android 单元测试从入门到放弃
主要介绍本地测试使用的技术框架,依赖库的优缺点:
● Gradle For Android(6)--测试单元
介绍AndroidStuido中如何使用单元测试相关工具
● mockito框架使用总结
介绍mocktio的APi,如何使用
● 2023单元测试利器Mockito框架详解
● PowerMockito使用详解
● Android最佳Mock单元测试方案:Junit + Mockito + Powermock
介绍目前比较实用的测试单元框架的使用
● Robolectric使用教程
可支持Android UI框架的测试库,覆盖范围比mockito,powermockito更宽
● Android 单元测试之Robolectric
框架库原码工程及文档
Mockito 中文文档
MockKotlin
支持kotlin的mockito库,主要是代码写法和格式为kotlin格式
PowerMockito
mockito的加强版,支持的范围比mockito大些
Robolectric
上一篇
数据测试
下一篇
Bundletool架包
Loading...