【ArchSummit架构师峰会】探讨数据与人工智能相互驱动的关系>>> 了解详情
写点什么

自动化测试基础设施(一)——为功能测试构建通用 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:1510694

评论

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

PoseiSwap:基于 Nautilus Chain ,构建全新价值体系

EOSdreamer111

为什么马斯克和奥特曼都想重振加密货币?

树上有只程序猿

人工智能 AGI

亚信科技AntDB数据库专家出席数据库标准研讨会并参与研讨

亚信AntDB数据库

数据库 AntDB AntDB数据库 企业号 8 月 PK 榜

数字孪生in电力终端:高效虚拟环境实现测试“左移”

DevOps和数字孪生

数字孪生 虚拟测试

【华秋干货铺】PCB布线技巧升级:高速信号篇

华秋电子

PoseiSwap:基于 Nautilus Chain ,构建全新价值体系

鳄鱼视界

深入探究DDD领域建模的方法:从概念到实践

高端章鱼哥

微服务 领域驱动设计 DDD 单体

基于分级安全的OpenHarmony架构设计

OpenHarmony开发者

OpenHarmony

高质量代码究竟依赖设计还是重构而来?

CODING DevOps

瓴羊QuickBI的数据门户功能可以大大简化和提高数据分析的效率

小偏执o

案例上榜 | Kyligence x 中国平安人寿北斗指标设计平台

Kyligence

数据分析 数智化

“科创中国”青百会轮值主席吴甜:以大语言模型为代表的AI将引发产业变革

飞桨PaddlePaddle

人工智能 百度 paddle 飞桨 百度飞桨

从零开始学极狐GitLab|02 基本功能使用

极狐GitLab

DevOps gitlab 用户管理 项目创建 群组创建

Sprint Boot学习路线5

小万哥

Java spring 微服务 springboot SpringCloud

PoseiSwap:基于 Nautilus Chain ,构建全新价值体系

西柚子

聊聊 Docker 和 Dockerfile

互联网工科生

Docker 容器 Dockerfile

官宣 | CODING 荣获可信云软件研发效能度量平台先进级最高评估成果

CODING DevOps

Base链怎么快速发币?2分钟创建一个土狗币

加密先生

发币教学 一键发币

PoseiSwap:基于 Nautilus Chain ,构建全新价值体系

BlockChain先知

CentOS7上安装Squid代理详细教程【附带使用教程】

百度搜索:蓝易云

云计算 Linux centos 运维 squid

罗拉IP服务关停?哪些靠谱的IP代理商可以作为替代方案?"

摘星星的猫

IP 网络

PoseiSwap:基于 Nautilus Chain ,构建全新价值体系

股市老人

开心档之DTD - 元素

雪奈椰子

基于Kubernetes环境的高扩展机器学习部署利器——KServe

高端章鱼哥

机器学习 Kubernetes ML

数据分析的提升,通过领羊QuickBI数据功能可以简化

夏日星河

MySQL2 和 MySQL 有什么区别?

这我可不懂

MySQL 性能 维护

极狐GitLab 全新「价值流仪表盘」使用指南

极狐GitLab

DevOps gitlab DevSecOps DORA 价值流仪表盘

PoseiSwap:基于 Nautilus Chain ,构建全新价值体系

威廉META

【报名开启】AIGC 交响乐奏起!亚马逊云科技开发者社区嘉年华 2023 上海站报名通道开启!

亚马逊云科技 (Amazon Web Services)

AI 科技

以指标驱动,保险、零售、制造企业开启精益敏捷运营的新范式

Kyligence

数据分析 数智化

CentOS7查看开放端口命令、查看端口占用情况和开启端口命令、杀掉进程等命令教程。

百度搜索:蓝易云

云计算 Linux centos 运维 端口

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