【测试沉思录】10. 我们用到的3种Mock测试方案

news2024/9/9 5:02:28

欢迎订阅我的新专栏《现代命令行工具指南》,精讲目前最流行的开源命令行工具,大大提升你的工作效率。

作者:王媛媛 编辑:毕小烦

Mock 这个词对于测试人员来说并不陌生,当我们要测试的接口 A 依赖接口 B ,可 B 无法满足我们的测试需求时,需要 Mock 一下接口 B,来测试 A。当前端和服务端并行开发时,如果服务端接口还没有开发好,前端同学也会 Mock 一下。

那 Mock 到底是什么?

维基百科:

在面向对象程序设计中,模拟对象(英语:mock object,也译作模仿对象)是以可控的方式模拟真实对象行为的假的对象。程序员通常创造模拟对象来测试其他对象的行为,很类似汽车设计者使用碰撞测试假人来模拟车辆碰撞中人的动态行为。

注意这里的关键信息,以可控的方式,模拟真实对象行为,假的对象。

为什么要模拟呢?

一定是因为没有办法或者不需要用真实的服务,比如:

  • 真实的对象还没开发好,但你又急需测试;
  • 真实的对象是第三方的(比如各种开放平台),没有提供联调环境,或是不便联调,或是搭建很麻烦;
  • 真实的对象无法覆盖你要的测试场景(比如网络错误),而使用 Mock,你想要什么就可以模拟什么;
  • 真实的对象速度很慢,而模拟的非常快;
  • 等等。

这些情况下,模拟对象是一个非常好的解决方案,它可以让你的测试不被阻断,还能模拟出你想要的各种场景。

但模拟,不是真实,模拟是按照我们设定的剧本在走,是我们自己控制的,而真实的情况可能存在各种不确定性,所以不能完全相信 Mock。另外,Mock 是把真实对象模拟了一遍,如果真实对象改了,模拟对象也得跟着改,数量一多,维护起来也是十分的麻烦。

怎么 Mock ?

本文介绍我们团队在实际的项目中遇到的 3 种 Mock 场景,以及我们的设计方案。

案例1. Mock HTTP:通过域名映射实现 Mock

项目背景

我们要测试一个 HTTP 接口,这个接口在服务内部的处理会因地区不同而存在差异,虽然对外提供的业务接口只有 1 个,但在服务内部,如果判断是 A 地区就会去调用 A 地区的接口,B 地区会去调用 B 地区的接口,不同地区通过域名区分。

比如,要测的是登录接口 test.com/login,到了内部处理时就会因不同的地区去调用不同接口:

  • A 地区会调用:test.a.com/login
  • B 地区会调用:test.b.com/login
  • C 地区会调用:test.c.com/login

如下所示:

img

为了便于测试,我们需要 Mock 各个地区的接口,应该怎么做呢?

设计方案

方案如下:

img

在「中台」所在的服务器上,将调用 A 地区接口的域名通过 hosts 中的配置映射到 Mock 平台的 IP。配置好以后,「中台」调用 A 地区的接口时,请求都会转发到 Mock 服务器上,然后我们就可以在 Mock 服务器上对具体的接口进行配置,定制返回信息;

需要 Mock 多个地区时,将对应域名加到 hosts 里映射即可。当然也可以 Mock 一个固定的域名,如 test.mock.com,然后每个地区的域名进行配置化(配置中心)。当我们要 Mock 某个地区时,只需将该地区的配置的域名改为 test.mock.com 即可,这样就不用去修改 hosts 文件了。

这种方案的优点是:

  1. 没有代码侵入,域名可通过 hosts 进行配置,将不同的域名映射到 Mock 服务器;
  2. 配置简单,没有什么门槛;

缺点是:

  1. 依赖的数据需要我们自己来配置,这需要额外投入精力去研究被依赖服务的接口信息,还要维护 Mock 数据;
  2. Mock 控制粒度比较粗。在无任何代码侵入的前提下,比如在测试 A 地区的接口时,需将被调用的所有接口都进行 Mock,而不能只 Mock 其中几个接口。
  3. 仅支持 Mock HTTP 请求。

案例2. Mock RPC:基于 AOP 实现 Mock

项目背景

这个项目对另外一个项目有强依赖,并且我们对这个 Mock 方案的要求是,除了能满足我们自己的常规测试外,还要能提供给外部客户进行快速对接、联调,要能支持 HTTP 和 RPC(Dubbo)。

设计方案

为了满足这个需求,我们开发了 Mock SDK

SDK 中包含几个拦截器:

  1. AbstractAspect 类:是一个抽象切面拦截器,是其它拦截器的父类,提供了一些抽象方法让子类实现,以及一些通用的方法。
  2. ControllerAspect 类:HTTP 接口拦截器,负责获取接口的 URL、获取全部请求头、获取全部请求参数、获取全部请求体数据。
  3. FacadeAspect 类:Dubbo 接口拦截器,负责获取方法名及其参数。
  4. AnnotationsAspect 类:注解切面拦截器,当 Java 类不在 client 下,但是需要 Mock 对应的方法时,可以在该方法前加上注解 @Mock

使用时只需:

  1. pom 文件中引入 Mock SDK;
  2. spring-scan-bean 配置 Mock 的工具类,加载到 spring 上下文容器中;
  3. 设置 Mock 开关配置。开启 Mock 模式时,默认会对所有 controller 中的接口、client 中的 Dubbo 方法以及所有加了 Mock 注解的方法进行拦截。

方案如下:

img

这种方案的优点是:

  1. 支持 Mock HTTP,提供给客户联调测试时可在 controller 层进行 Mock,但不推荐这么做,客户自己 Mock HTTP 接口会更灵活;
  2. 支持 Mock RPC,我们自己测试时可在 client 层进行 Mock;
  3. Mock 粒度更细:支持按接口粒度进行 Mock,还支持单个 Java 方法添加注解来实现 Mock;
  4. Mock 节点灵活:controller 层、client 层、或加了 Mock 注解的 Java 方法均可。

缺点是:

  1. 性能问题:在 Mock 开启模式下,每次请求都会去判断是否存在 Mock 对象,接口性能会有一定程度受影响。
  2. Dubbo 接口目前只在 client 层做的切面,所以在 Mock 平台配置返回值时,出参字段没办法从接口文档中直接获取,因为 client 层的出参字段与接口文档的参数字段不完全一致。
  3. 存在代码侵入。就算在 Mock 配置为关闭的情况下,仍会生成一个无逻辑的切面。

案例3. Mock Python:基于数据存储中间件实现 Mock

项目背景

该项目也是需要对接多个区域,不同区域的接口存在很大差异,而且被测服务的末端是 Python 服务。另外一个重要的点是:该项目的测试数据非常有限且不可重复利用。

其实用「方案1」去 Mock 接口也是可以的,但:

  1. 需要花很多时间去预研 Mock 数据;
  2. 被依赖服务的接口加解密方式、调用链路差异很大;
  3. 配置成本过高:比如一个登录功能,有些区域可能需要调 5 个接口,有些可能要 7 个接口才能实现;为了实现一个业务功能,往往需要配几十个接口的 Mock。

因此在权衡了时间、资源、风险利弊之后,我们采取了新的 Mock 方案 —— 基于数据存储中间件的 Mock,我们用的是 Redis。

设计方案

基于数据存储中间件的 Mock 方案其实是在被测服务中加入 Mock 逻辑,当启用 Mock 时,直接从 Redis 获取数据,而不去请求真实的数据,这就实现了 Mock 的目的。

img

Mock 方法:

  1. 配置 Mock 开关,便于开启和关闭;
  2. 在 Redis 中配置 Mock 对应的 Key/Value

优点:

  1. 无需额外搭建 Mock 平台,研发投入成本低;
  2. 无需关注各区域接口差异,Mock 的数据格式统一;
  3. 配置和维护成本低,也可编写脚本实现批量 Mock。

缺点:

  1. 业务代码验证不全,Python 服务的业务代码是验证不到的。所以,Mock 测试之后,还要用仅存的真实数据去验证一遍。
  2. 存在代码侵入。为实现 Mock 功能,存在非业务性逻辑。

总结

上述这 3 个案例就是我们在实际项目中遇到并实践过的 Mock 方案,当然还有其他的方案,这需要结合项目的实际情况综合评估风险、资源、利弊后再做选择。本文只是提供了一些思路,希望对大家有所启发。

(完)

如果文章对你有帮助,记得留言、点赞、加关注哦!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2455.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

CSS3专题-[上篇]:过渡、2D转换、动画

目录 CSS3:前置特性 CSS3:盒子模型 CSS3:图片滤镜与模糊处理 blur():高斯模糊 CSS3:计算盒子宽度calc()函数 CSS3:过渡效果 transition属性 2D转换:transform属性 translate()方法 * t…

11、Microsoft Visual Studio 2022 Installer Projects踩坑一

前言:VS自带的打包工具对于单文件简单程序很好用,对于多文件涉及到依赖其他程序就需要多一点配置了,之前打包过一个简单程序,后来程序变大后再执行生成的时候就出现问题了,要么执行不成功,要么生成成功安装…

猿创征文|后端开发工程师提升开发效率神器推荐

简介 对于现在的后端工程师来说,并不仅仅局限于编写代码和解决bug,这两个要素了。如果你目前还只是忙碌的写代码和改bug的话,那要深度思考一下,我为什么日复一日的写这些重复代码?这样有何意义?或者说&…

Java开发必须掌握的运维知识 (七)-- 性能监控日志收集,数据实时分析存储工具Influxdb实战

从这节起,我们要循序渐进的学习InfluxDB、Cadvisor、Grafana。这三种工具组合使用可以完成对容器的各项指标实时监控,也为后面的k8s打好基础。 一、InfluxDB的介绍 InfluxDB是一种用Go编写的时间序列数据库,主要用来存储一些时间序列的数据…

项目管理之沟通管理

目录 前言 一、沟通模型是什么? 二、项目沟通管理过程 三、规划沟通管理 1.规划沟通管理的ITO 2.工具与技术的使用 四、管理沟通 1.管理沟通的ITO 2.三种绩效区别 五、控制沟通 1.控制沟通的ITO 2.工具与技术的使用 总结 前言 本文章主要介绍以下项目…

JVM垃圾回收——三色标记法

目录 一、什么是三色标记 二、三色标记的过程 三、三色标记的缺点 四、垃圾回收机如何弥补三色标记的缺点 在CMS、G1这种并发的垃圾收集器收集对象时,假如一个对象A被GC线程标记为不可达对象,但是用户线程又将A对象标记为可达对象,那么此…

基于Session实现短信登录

目录 一、基于Session实现登录 1.1 业务流程图​编辑 二、发送短信验证码 2.1 发送短信请求方式及参数说明 2.2 业务层代码模拟发送短信 三、登录功能 3.1 短信验证的请求方式及路径 3.2 业务层代码实现用户登录 3.3 拦截器——登录验证功能 三、隐藏用户敏感信息 …

React-Hooks源码深度解读

useState 解析 useState 使用 通常我们这样来使用 useState 方法 function App() {const [num, setNum] useState(0);const add () > {setNum(num 1);};return (<div><p>数字: {num}</p><button onClick{add}> 1 </button></div>…

前Zynga中国总裁田行智联合创办的亚创拟上市:市值25亿美元 公司PPT曝光

雷递网 雷建平 10月31日前Zynga中国总裁田行智&#xff08;Andy Tian&#xff09;联合创办的亚洲创新集团&#xff08;Asia Innovations Group Limited&#xff0c;简称“亚创集团”&#xff09;日前拟通过SPAC模式上市。亚创集团已与特殊目的收购公司&#xff08;SPAC&#xf…

【C++】内联函数auto关键字基于范围的for循环指针空值nullptr

​&#x1f320; 作者&#xff1a;阿亮joy. &#x1f386;专栏&#xff1a;《吃透西嘎嘎》 &#x1f387; 座右铭&#xff1a;每个优秀的人都有一段沉默的时光&#xff0c;那段时光是付出了很多努力却得不到结果的日子&#xff0c;我们把它叫做扎根 目录&#x1f449;内联函数…

Bitquery与Moonbeam集成,为多链提供链上数据访问

Moonbeam是一个智能合约平台&#xff0c;用于构建跨链互连应用程序&#xff0c;能够访问任何链上的用户、资产和服务。通过将来自以太坊、Cosmos、波卡等功能整合到一个平台中。近日&#xff0c;Moonbeam与Bitquery集成&#xff0c;为市场分析、资金流、DeFi等多链提供链上数据…

JavaScript 53 JavaScript 箭头函数

JavaScript 文章目录JavaScript53 JavaScript 箭头函数53.1 语法53.2 this 怎么办&#xff1f;53.2.1 常规函数53.2.2 箭头函数53.3 浏览器支持53 JavaScript 箭头函数 ES6 中引入了箭头函数。 箭头函数允许我们编写更短的函数 53.1 语法 以前定义函数 hello function() …

一位小镇做题家的付费咨询

前几天&#xff0c;有位知乎读者咨询我&#xff0c;感觉很迷茫&#xff0c;不知道做什么。这可能也是大多数在校大学生的状态&#xff0c;忙忙碌碌&#xff0c;浑浑噩噩&#xff0c;不知道该怎么办。 首先&#xff0c;不管从事哪个行业&#xff0c;你的学历一定是亮点。专业的话…

Flutter ChoiceChip 用来实现选择标签效果

程序员如果敲一会就停半天&#xff0c;抱着一杯茶&#xff0c;表情拧巴&#xff0c;那才是在编程&#xff0c;在之前我要实现一级标签效果&#xff0c;我还在苦苦写了好多嵌套的代码&#xff0c;当我看到 Clip 时&#xff0c;泪奔啊&#xff0c;原来一个组件就可以实现&#xf…

(8个方法)解决windows11/10/8/7卡在准备就绪一直转圈

许多用户会遇到Win10安装卡在准备就绪一直转圈的情况或者重装系统准备就绪转圈的问题。也有一些用户反映&#xff0c;Win10准备就绪后黑屏重启&#xff0c;一直循环。一开始大家会耐心等待&#xff0c;但是等了很久后发现没什么用&#xff0c;这该怎么办&#xff1f;本文教你一…

第32讲:MySQL数据库的体系结构组成

MySQL数据库的体系结构组成 MySQL数据库整个体系结构可以分为五个部分,如下图所示: 1)客户端连接器 这一层也是整个MySQL体系中的最上层,包含本地Sock通信和支持大多数客户端到服务端的TCP通信,像JAVA的JDBC、Python、PHP都可以连接到MySQL数据库。 2)数据库连接层 客…

嵌入式分享合集92

一、常用电路基础公式 1.欧姆定律计算 计算电阻电路中电流、电压、电阻和功率之间的关系。 欧姆定律解释了电压、电流和电阻之间的关系&#xff0c;即通过导体两点间的电流与这两点间的电势差成正比。说明两点间的电压差、流经该两点的电流和该电流路径电阻之间关系的定律。该…

2022年了,软件测试已经饱和了?

这个年头找工作跟找对象一样难&#xff0c;咳咳&#xff0c;工作对象都木有&#xff0c;双重打击5555。 关于今年的就业市场&#xff0c;很多人表示特别惨淡&#xff0c;以往简历一投就有大批企业来联系&#xff0c;今年自己投递一大堆简历出去&#xff0c;可能全部都是已读不…

链路状态路由协议OSPF——理解OSPF多区域原理

作者简介&#xff1a;一名在校云计算网络运维学生、每天分享网络运维的学习经验、和学习笔记。 座右铭&#xff1a;低头赶路&#xff0c;敬事如仪 个人主页&#xff1a;网络豆的主页​​​​​​ 目录 前言 一.OSPF的多区域 1.OSPF概述 2.生成OSPF多区域的原因 二.OSP…

ArrayList源码解析(JDK8)

文章目录一、ArrayList继承体系二、ArrayList属性三、构造方法1、ArrayList(int initialCapacity)2、ArrayList()3、ArrayList(Collection<? extends E> c)四、ArrayList 相关操作方法1、add(E e)2、add(int index, E element)3、addAll(Collection<? extends E>…