稀土掘金 稀土掘金

干货!用大白话告诉你什么是Mock测试

本文 github.com/smileArchit… 已收录。
JavaMap是Java知识地图,旨在让开发者学习不迷路!Java学习请认准JavaMap。

初识mock

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

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

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

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

文字不好理解,我们画个图,如下图所示,被测试对象是 A,A 依赖的是B,B 依赖的是 C。而我们要 mock 的是 B 的行为。图中 A 就是 SUT。

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

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

mock 种族

常见的 mock 类型如下图所示:

从下往上依次解释一下:

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

接口mock注入的五种方式

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

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

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

什么是 mock 注入?

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

如何注入 mock?

总的来说 mock 桩的注入方式与架构、被测服务的架构等因素相关,在实际中常见的 mock 桩注入方式包括但不限于以下五种。

(1)API 请求构造

在 mock 接口中被测服务是 API 的请求方,即客户端;依赖服务是 API 的响应方,即服务端。根据 mock 工作的位置,mock 可以分为客户端 mock服务端 mock

客户端 mock:mock 在被测服务内部工作,直接拦截被测服务的 API 请求方法(比如 HTTP Client方法),在被测服务调用 API 请求方法时,直接从方法内部返回预定义的 mock 响应。

服务端 mock:mock 在被测服务外部工作,作为 HTTP 服务器接收被测服务发送的 API 请求,并返回预定义的 mock 响应。

客户端 mock 的注入其实就是改造被测服务的 API 请求方法,即在 API 请求方法中加入 mock 处理逻辑。当满足某些条件时执行 mock 分支,不满足时执行真实分支。

可以通过两种方式实现,一种是直接改造源代码另一种是利用字节码增强技术对字节码进行改造(Java 语言)

API 请求改造这种注入方式适用于客户端 mock,其优势性能极好,其不足是实现成本较高。

(2)本地配置

对于服务端 mock,打桩之后会生成唯一的 mock 桩地址。被测服务要想调用这个桩需要知道桩地址,如何让被测服务知道桩地址呢?一种最直接的方法就是被测服务提供一个依赖服务地址配置项,在需要使用 mock 时将依赖服务地址修改成 mock 地址。

本地配置的优势是实现简单,不足之处是修改配置项需要重启被测服务,在需要进行 mock 服务与真实服务切换时不方便。

(3)配置中心

在服务端 mock 中,为了避免修改依赖服务地址配置项导致被测服务重启,可以采用配置中心(如 Spring Cloud Config Server)存储和管理依赖服务地址配置,或者使用注册中心(如 Spring Cloud Eureka)记录服务与服务地址的映射关系。

使用配置或者注册中心时,mock 注入的方法是修改配置中心,将依赖服务地址改成 mock 地址。这种注入方法不需要重启被测服务,但是从配置改变到配置生效可以存在一定的延时

(4)反向代理

在微服务架构下,被测服务与依赖服务之间可能不是直连的,而是经过了一层反向代理,例如 API 网关。在这种情况下,被测服务是通过调用 API 网关来间接调用依赖服务的接口。

在 API 网关模式下,mock 注入的具体做法就是修改 API 网关配置,将依赖服务 API 网关接口绑定的地址改成 mock 地址。

这种注入的优势是对被测服务无侵入,并且实现更细粒度(接口级)的 mock。当然,根据 API 网关的实现不同,仍然可能存在一定的时延。亚马逊 AWS 的 API 网关就是采用这种方式进行 mock。

(5)前向代理

服务端 mock 除了作为 HTTP 服务器,还可以兼备 HTTP 代理的功能,这种架构又叫做 mock 代理,例如 mock server proxy。对于 mock 代理来说,它不仅能够返回 mock 响应,而且能够在需要的时候将 API 请求转发给依赖服务,并将依赖服务的真实响应返回给被测服务。

使用前向代理模式,mock 注入的方式是将被测服务的依赖地址或网络代理修改为 mock 地址,这种注入方法需要重启被测服务,其优势是能够实现细粒度的 mock,并且能够根据录制的真实响应自动生成 mock。

五种注入方式对比

一张表格总结一下

不可忽视的mock两大功能

关于 mock,经常容易被误解的是:认为 mock 只是模拟返回的结果而已。

实际上 mock 还可以提供两大功能: (1)记录真实的调用信息; (2)生成模拟的返回信息;

对于测试用例来说,我们不仅关心 mock 是否返回了期望的结果,还需要关心 SUT 是否以期望的方式调用了 mock 对象。

如果 SUT 没有以期望的方式调用,比如:没有传参或者参数不对,那么 SUT 就存在问题。

mock 需要详细记录来自SUT 的调用信息,并提供给用例来校验。比如 Java mockito 就提供了此类校验功能:

List<String> mockedList = mock(MyList.class);
mockedList.size();
// 校验 size 函数调用且只调用了1次
verify(mockedList, times(1)).size();

常用 mock 工具

单元测试级别

这个级别的mock工具有easymock、jMock、Mockito、Unitils Mock、PowerMock、JMockit等,关于各自优劣势大家可以上网查询。

接口测试级别

接口级别的mock工具完成的主要功能是对一个用户的请求,模拟server返回一个接口的响应数据。常用的有:

  • Wiremock
  • Mockserver
  • Moco
  • Mock.js
  • RAP

mock 不是银弹

说了这么多 mock 的好处,实际上 mock 也有很多不足,比如:

  • (1)mock 可能导致问题遗漏。mock 的模拟行为与真实行为可能存在 GAP,导致基于 mock 的测试虽然通过了,但是基于真实对象的测试却失败了,这意味着问题被遗漏了。 mock 很难模拟所有的真实情况。
  • (2)mock 带来较高的维护成本。基于 mock 的测试用例结构比较复杂,实现和维护都不容易,后期被测代码有变动时需要适配 mock 代码。

简单一句话:mock 不是银弹。

有态度的总结

mock 不是银弹,mock 是有利有弊的,一张图总结一下:

说了这么多,在工作中如何正确使用 mock 呢?这里提两点建议。

(1)不要过度使用 mock。测试用例中掌握好使用 mock 的度。在涉及网络访问、数据库读写、操作系统交互等系统级调用,优先使用 mock。

(2)不要过度依赖基于 mock 的测试结果。基于 mock 的测试无论多么充分,这都不能保证不出现问题的遗漏。一个完整的测试策略一定是由基于 mock 的测试和基于非 mock 的测试共同组成的,二者相辅相成缺一不可。

-- END --

不要白嫖,点个赞咯,笔芯~

作者简介:
☕读过几年书:华中科技大学硕士毕业;
😂浪过几个大厂:华为、网易、百度……
😘一直坚信技术能改变生活,愿保持初心,加油技术人!

微信搜索公众号【爱笑的架构师】,关注这个对技术和生活有追求的技术人。

最后推荐一个宝藏开源项目, github.com/smileArchit… 
JavaMap是Java知识地图,让开发者学习不迷路!Java学习请认准JavaMap。
JAVA核心知识点整理(283页,超级详细)免费领取。

玻璃钢生产厂家儿童商场美陈方案太原公园玻璃钢雕塑制作不锈钢镂空玻璃钢景观雕塑生产河北艺术商场美陈批发价玻璃钢鹿雕塑哪家有名厂家玻璃钢雕塑吉林市玻璃钢雕塑设计玻璃钢仿真雕塑型号河北泡沫玻璃钢雕塑商场美陈装饰气球玻璃钢人像雕塑公司哪家好芜湖百货商场美陈玻璃钢雕塑爆米花小贩玻璃钢雕塑运用玻璃钢花盆花钵酒店玻璃钢雕塑设计费用南充玻璃钢南瓜屋雕塑孔子玻璃钢雕塑厂家定制雕塑玻璃钢广东特色商场美陈生产厂家仙桃玻璃钢门头雕塑商场美陈特装有没有保障佛山联尖玻璃钢雕塑厂甘南仿真人物玻璃钢雕塑定做建安玻璃钢雕塑定制商场美陈布置地铁站韶关玻璃钢雕塑厂家现货赣州玻璃钢雕塑服务商芝麻街玻璃钢雕塑厂家福州小区玻璃钢雕塑安装香港通过《维护国家安全条例》两大学生合买彩票中奖一人不认账让美丽中国“从细节出发”19岁小伙救下5人后溺亡 多方发声单亲妈妈陷入热恋 14岁儿子报警汪小菲曝离婚始末遭遇山火的松茸之乡雅江山火三名扑火人员牺牲系谣言何赛飞追着代拍打萧美琴窜访捷克 外交部回应卫健委通报少年有偿捐血浆16次猝死手机成瘾是影响睡眠质量重要因素高校汽车撞人致3死16伤 司机系学生315晚会后胖东来又人满为患了小米汽车超级工厂正式揭幕中国拥有亿元资产的家庭达13.3万户周杰伦一审败诉网易男孩8年未见母亲被告知被遗忘许家印被限制高消费饲养员用铁锨驱打大熊猫被辞退男子被猫抓伤后确诊“猫抓病”特朗普无法缴纳4.54亿美元罚金倪萍分享减重40斤方法联合利华开始重组张家界的山上“长”满了韩国人?张立群任西安交通大学校长杨倩无缘巴黎奥运“重生之我在北大当嫡校长”黑马情侣提车了专访95后高颜值猪保姆考生莫言也上北大硕士复试名单了网友洛杉矶偶遇贾玲专家建议不必谈骨泥色变沉迷短剧的人就像掉进了杀猪盘奥巴马现身唐宁街 黑色着装引猜测七年后宇文玥被薅头发捞上岸事业单位女子向同事水杯投不明物质凯特王妃现身!外出购物视频曝光河南驻马店通报西平中学跳楼事件王树国卸任西安交大校长 师生送别恒大被罚41.75亿到底怎么缴男子被流浪猫绊倒 投喂者赔24万房客欠租失踪 房东直发愁西双版纳热带植物园回应蜉蝣大爆发钱人豪晒法院裁定实锤抄袭外国人感慨凌晨的中国很安全胖东来员工每周单休无小长假白宫:哈马斯三号人物被杀测试车高速逃费 小米:已补缴老人退休金被冒领16年 金额超20万

玻璃钢生产厂家 XML地图 TXT地图 虚拟主机 SEO 网站制作 网站优化