作为一个动词,mock是模拟、模仿的意思;作为一个名词,mock是能够模仿真实对象行为的模拟对象。

初识 Mock

在软件测试中,mock所模拟的对象是什么呢?

它一定不是我们所测试的对象,而是 SUT 的依赖(dependency)。换句话说,mock 的作用是模拟 SUT 依赖对象的行为。

测试的对象一般称之为 SUT(Software Under Test)

被测试对象是 A,A 依赖的是B,B 依赖的是 C。而我们要 mock 的是 B 的行为。

A: 被测试对象

B: 直接依赖对象

C: 间接依赖对象

为什么需要模拟 B 的行为呢?

  • 提高 A 的测试覆盖率。A 依赖 B,本质上依赖的是 B 的返回结果,也就是说 B 的返回结果会影响 A 的行为。通过 mock B 我们可以构造各种正常和异常的来自 B 的返回结果,从而更充分测试 A 的行为。
  • 避免 B 的因素从而对 A 产生影响。依赖真实的 B 去测试 A 可能有很多问题:B 的开发没有完成时无法测试 A;B 有阻塞性bug 时无法测试 A;B 的依赖 C 有阻塞性 bug 时无法测试 A;
  • 提高 A 的测试效率。B 的真实行为可能很慢,而 B 的模拟行为是非常快的,因此可以加快 A 的测试执行速度。

Mock 种族

从下往上依次解释一下:

  • 方法级别 mock:mock 的对象是一个函数调用,例如获取系统环境变量。
  • 类级别 mock:mock 的对象是一个类,例如一个 HTTP server。
  • 接口级别 mock:mock 的对象是一个 API 接口。
  • 服务级别 mock:mock 的对象是整个服务。比如前端工程师自测试时,可以讲后端整个服务都 mock 掉,这其实等同于将后端的所有接口都 mock。

接口 Mock 注入的五种方式

在使用 mock 进行接口测试时,一般要做两件事情,即打桩和调桩。

其实打桩就是创建 mock 桩,指定 API 请求内容及其映射的 mock 响应内容;所谓调桩就是被测服务来请求 mock 桩并接收 mock 响应。

事实上,在打桩和调桩之间还隐藏着一件不显山露水、但是及其重要的事情,那就是 mock 桩的注入(mock injection)。

什么是 mock 注入?

mock 的本质就是用模拟桩来替换真实的依赖。所谓 mock 桩注入就是阻断被测服务与真实服务之间的链路,建立被测服务与 mock 之间的链路过程。