文档适用范围:所有涉及使用Mockito的单元测试场景都可参考本文档内容。
1. Mock概念的理解
在传统的JUnit单元测试中,没有消除在测试中对对象的依赖,如A对象依赖B对象方法,在测试A对象的时候,我们需要构造出B对象,这样子增加了测试的难度,或者使得我们对某些类的测试无法实现。这与单元测试的思路相违背。
还有一个主要的问题就是本地单元测试由于是运行本地JVM环境, 无法依赖Android的api,只靠纯Junit的测试环境很难模拟出完整的Android环境,导致无法测试Android相关的代码,而Mock就能解决这个问题,通过Mock能够很轻易的实现对象的模拟。
添加依赖:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
// 具体版本请参考BasicApp内的config.gradle
testImplementation 'org.mockito:mockito-core:2.19.0'
}
2. Mockito中几种Mock对象的方式
直接mock一个对象:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vg5OzWt9-1590740454159)(Mockito使用说明文档.assets/image003.png)]
运行器方式mock一个对象:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fccF21Gc-1590740454168)(Mockito使用说明文档.assets/image004.png)]
MockitoRule方式mock一个对象:
3. 验证行为
verify(T mock)函数的使用
通常需要配合一些测试方法来验证某些行为,这些方法称为"打桩方法"(Stub),打桩的意思是针对mock出来的对象进行一些模拟操作,如设置模拟的返回值或抛出异常等。
常见的打桩方法:
doXXX和thenXXX使用上差不多,一个是调用方法之前设置好返回值,一个是在调用方法之后设置返回值。默认情况下,Mock出的对象的所有非void函数都有返回值,对象类型的默认返回的是null,例如返回int、boolean、String的函数,默认返回值分别是0、false和null。
使用when(T methodCall)函数
打桩方法需要配合when(T methodCall)函数,意思是使测试桩方法生效。当你想让这个mock能调用特定的方法返回特定的值,那么你就可以使用它。
使用thenAnswer为回调做测试桩
使用doCallRealMethod()函数来调用某个方法的真实实现方法
注意,在Mock环境下,所有的对象都是模拟出来的,而方法的结果也是需要模拟出来的,如果你没有为mock出的对象设置模拟结果,则会返回默认值,例如:
因为getName()方法没有设置模拟返回值,而getName()返回值是String类型的,因此直接调用的话会返回String的默认值null,所以上面代码如果要想输出getName()方法的真实返回值的话,需要设置doCallRealMethod():
使用doNothing()函数是为了设置void函数什么也不做
需要注意的是默认情况下返回值为void的函数在mocks中是什么也不做的但是,也会有一些特殊情况。如测试桩连续调用一个void函数时:
监控真实的对象并且你想让void函数什么也不做:
使用doAnswer()函数测试void函数的回调
4. 验证方法的调用次数
5. 参数匹配器 (matchers)
常用的参数匹配器:
6. 使用Spy监控真实对象
监控真实对象使用spy()函数生成,或者也可以像@Mock那样使用@Spy注解来生成一个监控对象, 当你你为真实对象创建一个监控(spy)对象后,在你使用这个spy对象时真实的对象也会也调用,除非它的函数被stub了。尽量少使用spy对象,使用时也需要小心形式。
使用@Spy生成监控对象:
有时,在监控对象上使用when(Object)来进行打桩是不可能或者不切实际的。因此,当使用监控对象时请考虑doReturn|Answer|Throw()函数族来进行打桩。例如:
7. 使用@InjectMocks自动注入依赖对象
有时我们要测试的对象内部需要依赖另一个对象,例如:
User类内部需要依赖Address类,当我们测试的时候需要mock出这两个对象,然后将Address对象传入到User当中,,Mockito 提供了可以不用去手动注入对象的方法,首先使用@InjectMocks注解需要被注入的对象,如User,然后需要被依赖注入的对象使用@Mock或@Spy注解,之后Mockito 会自动完成注入过程,例如:
更多使用方法请参考:https://github.com/hehonghui/mockito-doc-zh/blob/master/README.md#0