Mock 测试
Mock 最大的功能是帮你把单元测试的耦合分解开,如果你的代码对另一个类或者接口有依赖,它能够帮你模拟这些依赖,并帮你验证所调用的依赖的行为。
比如一段代码有这样的依赖:
当我们需要测试A类的时候,如果没有 Mock,则我们需要把整个依赖树都构建出来,而使用 Mock 的话就可以将结构分解开,像下面这样:
mock对象就是在调试期间用来作为真实对象的替代品。
mock测试就是在测试过程中,对那些不容易构建的对象用一个虚拟对象来代替测试的方法就叫mock测试。
Mock 对象使用范畴
- 真实对象具有不可确定的行为,产生不可预测的效果,(如:股票行情,天气预报)
- 真实对象很难被创建的
- 真实对象的某些行为很难被触发
- 真实对象实际上还不存在的(和其他开发小组或者和新的硬件打交道)等等
Mockito 使用
声明 mockito 依赖
|
|
示例
1. 验证行为
|
|
一旦创建 mock 将会记得所有的交互。你可以选择验证你感兴趣的任何交互
2. stubbing
|
|
- 默认情况下,所有方法都会返回值,一个 mock 将返回要么 null,一个原始/基本类型的包装值或适当的空集。例如,对于一个 int/Integer 就是 0,而对于 boolean/Boolean 就是 false。
- Stubbing 可以被覆盖。
- 一旦 stub,该方法将始终返回一个 stub 的值,无论它有多少次被调用。
- 最后的 stubbing 是很重要的 - 当你使用相同的参数 stub 多次同样的方法。换句话说:stubbing 的顺序是重要的,但它唯一有意义的却很少,例如当 stubbing 完全相同的方法调用,或者有时当参数匹配器的使用,等等。
3. 参数匹配器
Mockito 验证参数值使用 Java 方式:通过使用 equals() 方法。有时,当需要额外的灵活性,可以使用参数匹配器:
|
|
下面的示例演示验证,但同样适用于 stubbing:
|
|
4. 调用额外的调用数字/at least / never
|
|
times(1) 是默认的,因此,使用的 times(1) 可以显示的省略。
5. Stubbing void 方法处理异常
|
|
6. 有序的验证
|
|
有序验证是为了灵活 - 不必一个接一个验证所有的交互。
此外,还可以通过创建 InOrder 对象传递只与有序验证相关的 mock 。
7. 确保 mock 上不会发生交互
|
|
8. 寻找多余的调用
|
|
注意:不建议 verifyNoMoreInteractions() 在每个测试方法中使用。 verifyNoMoreInteractions() 是从交互测试工具包一个方便的断言。只有与它的相关时才使用它。滥用它导致难以维护。
9. 标准创建 mock 方式 - 使用 @Mock
注解
- 最小化可重用 mock 创建代码
- 使测试类更加可读性
- 使验证错误更加易读,因为字段名称用于唯一识别 mock
public class ArticleManagerTest {
|
|
在基础类或者测试 runner 里面,使用如下:
|
|
可以使用内建 runner: MockitoJUnitRunner 或者 rule: MockitoRule
更多详见 MockitoAnnotations
10. Stubbing 连续调用(迭代器式的 stubbing)
|
|
下面是一个精简版本:
|
|
11. 回调 Stubbing
允许使用泛型 Answer 接口。
然而,这是不包括在最初的 Mockito 另一个有争议的功能。建议只需用thenReturn() 或 thenThrow() 来 stubbing ,这在测试/测试驱动中应用简洁与简单的代码足够了。但是,如果有一个需要 stub 到泛型 Answer 接口,这里是一个例子:
|
|
案例:
|
|
|
|
|
|
测试案例:
|
|