写点什么

自动化测试基础设施(一)——为功能测试构建通用 mock server 系统

  • 2013-05-18
  • 本文字数:3371 字

    阅读完需:约 11 分钟

mock 在单元测试中已经众所周知。现今我们有各种功能强大而又好用的 mock 框架,可以很方便的解除单元测试中各种依赖,这大大的降低了编写单元测试的难度。而测试驱动开发(TDD)更进一步将 mock 作为一种设计手段,来辅助识别出元素之间交互的接口和职责。

那么在功能测试 (这里提到的功能测试指的是用户级测试) 这个层次,是否有必要使用 mock 呢?如果有必要又将如何构建呢?或者说是否有可能像单元测试中那样构建一个通用的 mock server 系统呢?本文将根据我的实践经历,向大家介绍一个通用 mock server 系统的主要组成部分以及设计思路。

Why

现今的业务系统很少孤立存在,它们或多或少需要使用兄弟团队或是其他公司提供的服务,这为我们的联调和测试造成了麻烦。对于这种情况,我们常见的解决方案是搭建一个临时的 server,模拟那些服务,提供数据进行联调和测试。这就是 mock server 的雏形。一般来讲,搭建这种 mock server 系统比较简单,不过它的功能也比较简单,而且往往需要针对不同的接口重复开发。那有没有可能像单元测试中使用的 mock 框架那样构建一个通用的 mock server 系统呢?

How

观察单元测试中的 mock 框架,我们会发现一般使用 mock 的流程是:

复制代码
init mock // 创建 mock 对象
config mock // 设置 mock 期望
setup mock // 将 mock 对象设置给被测对象
call // 调用被测接口,被测接口里的代码会调用 mock 对象
verify // 验证
拿 mockito 举例:
User expected = new User(“admin”, “12345”);
//init
UserDAO dao = mock(UserDAO.class);
//config
when(dao.findByName(“admin”)).thenReturn(expected);
//setup
UserService service = new UserService(dao);
//call
User actual = service.login(“admin”, “12345”);
//verify or assert

借鉴这种做法,我么就可以构建一个简单的 mock server 系统,接下来的内容中,我们会在这个 mock server 的基础上演化出比较完善的版本。

版本 1(简单的模拟值)

假设我们需要 mock 的是 HTTP 接口。我们的 mock server 提供一个配置接口 (对应着上面的 config mock 步骤),测试运行之前调用配置接口将需要 mock 的 HTTP 接口 URL 以及需要返回的值传递过去,mock server 内部建立 url 到返回值的关联 (这里就类似存在一个哈希表一样)。Mock server 还提供另外一个接口供被测系统调用。这是一个通用的接口,所有原先指向真实服务的地址全部被指向到该接口 (可以通过修改配置或修改系统 hosts 文件)。当该接口被调用时会寻找刚才建立的 url 到返回值的关联,并将 mock 的值返回。这样一个非常简单的 mock server 就构建出来了,对于一些简单的联调场景基本够用。这个时候我们的 mock server 的原理图如下面所示:

版本 2(提供调用参数的查询)

有了第一版的 mock server,对一些只需要模拟值的场景是够用了。但是,mock 的作用仅限于此么?想想单元测试中的 mock。在单元测试中 mock 框架除了能够为被测系统构建输入值外,还能捕获到被测程序传出的值,然后对这些值进行校验。举一个实际的例子:在我们的系统中经常需要向用户发送短信,为了对发送的短信功能以及短信内容进行验证,在没有 mock 之前我们可能真的需要向真实手机发送短信,然后验证。这不仅降低了测试效率,也增加了不少不可控因素。为此我给 mock server 添加第三个接口:query 接口。在被测系统调用 mock 接口时,mock 会记录下被测系统传递给 mock 接口的参数值,然后测试中可以调用 query 接口查询到记录的值,在测试中可以对其断言,而且这里记录下的调用记录还可以作为日志提供出来,提高系统的诊断能力。这样我们的 mock server 的结构就变成:

版本 3(可以根据参数模拟)

现在我们的 mock server 已经可以提供类似 verify 的功能了,但实际上它还不能算一个真正的 mock。它也不能处理哪怕稍微复杂一点的情况。在实际中,我们经常需要针对不同的参数返回不同的值。举个简单的例子:我们 mock 一个支付接口,对于订单号 123 我们期望支付成功,对于订单 234 期望支付失败。这就引入了我的 mock server 的两个核心组件:extractor 和 matcher。Extractor 组件主要用于从调用的参数上提取出参数值,然后转换成 key/value 的格式提供给后续的环节使用;因为请求的参数格式多种多样 (json,xml 等),extractor 为此提供了统一的接口。

Matcher 组件的作用是在拿到 extractor 传递过来的 key/value 值后利用一些匹配器匹配到具体设置的期望上,所有匹配到的调用会返回对应的值。也就是说 mock server 内部不再是简单的映射了。后面再介绍 DSL 部分的时候会介绍 matcher 使用的语法。这样我们的 mock server 结构就演化成下图:

版本 4(提供多种协议的支持)

估计有人在抱怨,说了这么多这个 mock server 还只能 mock HTTP 接口啊,我们的系统中存在 HTTP 接口,RPC 接口,SMTP 接口等等。这是 mock server 中协议组件的职责。协议组件是 mock server 的入口,它提供多种协议的服务,并且解析出协议包数据,然后将数据交给 extractor 组件;除此之外,协议组件在收到上层的返回值后,会按照协议的格式返回给被测系统 。利用一些开源的类库,我们可以很容易对一些通用协议提供支持,但对一些私有的二进制协议如果没有现成的库支持,要重新开发成本很大,不过我们可以从客户端来解决这个问题,这在后续的文章中会有介绍。

版本 5(模拟行为)

基本上一个功能还算完善的 mock server 成型了。但这就够了么?对于要模拟各种场景的测试还远远不够。我们很多接口有回调的功能,我们通常还需要模拟接口超时的情况,而对于一些支付相关的接口经常需要对参数进行加密解密,而且这些情况都需要是可配置的。有没有发现,前面我们介绍的所有实际上都是 mock 值。也就是我们设置一些值,然后调用的时候将值返回。但是很多时候我们不仅需要 mock 值,更要 mock 行为。这样我们有了 mock server 中最核心的组件:命令执行引擎 (好牛的名字,其实就那样)。在设置 mock 的时候我们不再是设置一个值,而是设置一个预定义命令组合成的流水线 (即按照类似下面 xml 的配置一步一步执行,并且可以将上一步的执行结果传递给下一步):

复制代码
<delay>1000</delay>
<callback url=http://localhost/callback.do>{“ret”:”true”}</callback>
<return>{“ret”:”true”}</return>

上面的流水线被命令执行引擎解析执行后就是按顺序执行对应的 DelayCommand, CallbackCommand 以及 ReturnCommand 命令了,具体命令就不介绍了。采取这种方式给我们 mock server 带来了很大的灵活性:只需要简单的扩展一个子命令,就可以扩充 mock server 的行为。比如 mock 某网关接口时需要使用 MD5 加密,只需要扩展一个 MD5Command(下面代码中的 $result 表示前一步骤 <md 5 /> 加密后的结果):

复制代码
<md5 />
<return>$result</return>

DSL

现在我们的 mock 不仅可以 mock 值了,对于各种行为的模拟也得心应手。但是要使用方便,还要提供便于使用的接口。Mock server 提供两类接口:针对自动化测试的 DSL,以及针对手工测试使用的管理界面。这里主要介绍这种 DSL(因为我们的测试用例是使用 xml 编写,转换成编程语言也很容易):

复制代码
<mock service=”http:/test.json” matcher=”hasKey($param.orderNo)”>
<delay>1000</delay>
<md5 />
<return>$result</result>
</mock>

service 是对被 mock 的服务的描述,比如对于 SMTP,我们可以这样定义: service=“smtp:9000”。这个表示在 9000 端口上监听 smtp 协议。而 matcher 即前面介绍的 matcher 组件所使用的各种匹配器,用于匹配被测系统调用 mock server 时传递的数据。比如上面的例子表示的就是如果被测系统调用 http 接口 /ticket.jsp,并且参数里包含 orderNo 则延迟 1 秒钟,然后返回一个 json 值 。

总结

前面几节介绍了一个比较完善的通用 mock server 从简到繁演化的设计思路,希望可以为想要构建类似设施的读者提供一个参照。

这个 mock 系统包含两个主要部分:mock admin 和 mock server。Mock admin 是管理界面,主要提供监控 (可以在界面上实时看到被测系统与 mock server 交互) 以及手工测试时的配置界面。 Mock server 即前面介绍的主体,其架构如上图所示。Mock server 包含几个核心组件:协议、extractor、matcher、命令执行引擎、存储 (即 mock server 中使用的各种数据的存储)。Mock server 提供三类接口:配置、被 mock 接口 (各种服务,通过协议组件提供)、查询。

2013-05-18 05:1511033

评论

发布
暂无评论
发现更多内容

Apipost接口自动化测试功能详解

测试人生路

Postman 自动化测试 接口自动化测试

湖南卫视携手华为云 打造跨年晚会“最炫科技风”

极客天地

消息收发弹性——生产集群如何解决大促场景消息收发的弹性&降本诉求

阿里巴巴云原生

阿里云 RocketMQ 云原生

Seata 1.6.0 正式发布,大幅度提升存储性能

阿里巴巴云原生

阿里云 seata

软件测试/测试开发丨如何确保API 的稳定性与正确性?你只需要这一招

测试人

软件测试 自动化测试 测试开发 RESTful API

Bonree ONE荣获信通院“2022IT新治理年度明星产品”

博睿数据

根因分析 博睿数据 荣誉奖项 Bonree ONE

2022 InfoQ 写作社区年度优质企业号评选名单公布!

InfoQ写作社区官方

热门活动

2022 OpenMLDB 硕果累累,颁奖台上荣耀连连

第四范式开发者社区

人工智能 机器学习 数据库 开源 特征

喜报|3DCAT入选“灵境杯”深圳市最佳元宇宙案例!

3DCAT实时渲染

虚拟现实 元宇宙 增强现实 实时云渲染 元宇宙开发

初识PHP(1):PHP是什么

华为云PaaS服务小智

php

WorkPlus平台多业务系统集成,让企业沟通协作更畅通

BeeWorks

Pytorch基础-tensor数据结构

嵌入式视觉

Tensor torch.tensor() Tensor维度

Pytorch基础-张量基本操作

嵌入式视觉

张量的基本操作 维度变换 索引切片 合并分割 卷积相关算子

InfoQ写作社区 2022 年度优质创作者评选名单公布!

InfoQ写作社区官方

热门活动

精华推荐 |【深入浅出Sentinel原理及实战】「原理探索专题」完整剖析Alibaba微服务架构体系之轻量级高可用流量控制组件Sentinel(1)

码界西柚

sentinel 1月日更 Sentinel 系统

关于接口测试自动化的总结与思考

阿里巴巴云原生

阿里云 云原生 TPS

云渲染动画价格一般多少?

Renderbus瑞云渲染农场

云渲染 云渲染价格

阿里云张献涛:无影,让计算触手可及

云布道师

无影云电脑

TiDB 6.5 LTS 发版

PingCAP

#TiDB

科技创新实力受认可,网易有道入选 2022 中国技术品牌影响力企业榜

有道技术团队

技术 数据分析

harbor从1.6.1升级至2.7.0

小黄鱼

Harbor

同盾科技 x TiDB丨实时数据架构为风控智能决策保驾护航

PingCAP

#TiDB

喜报 | 瑞云科技荣获“第四届天鸽奖十大创新企业”等两项大奖

3DCAT实时渲染

元宇宙 3DCAT 瑞云渲染

高性能存储SIG月度动态:DSMS开始适配Anolis OS、将在ANCK 5.10中支持ublk | 龙蜥 SIG

OpenAnolis小助手

开源 操作系统 高性能存储 龙蜥社区 sig

RayLink远程控制软件:叮~你收到一份年度关键词报告

RayLink远程工具

远程控制软件 RayLink

软件测试 | 测试开发 | 相比Selenium,Web自动化测试框架Playwright

测吧(北京)科技有限公司

测试

企业专用的即时通讯产品如何选择?

BeeWorks

Flutter Hero 动画组件的飞行过程显示控制

岛上码农

flutter ios 安卓 移动端开发 跨平台开发

卷积神经网络的压缩方法总结

嵌入式视觉

知识蒸馏 模型压缩 神经网络参数量化 二值化网络 模型剪枝

Kyligence 客户案例“泰康集团精细化经营分析与运营平台”获评数据智能最佳实践案例

Kyligence

数据分析 指标管理

Apipost——让前端、后端、测试共用一份API文档!

不想敲代码

自动化测试基础设施(一)——为功能测试构建通用mock server系统_软件工程_余昭辉_InfoQ精选文章