此文已由作者翟曜授权网易云社区发布。

欢迎访问网易云社区,了解更多网易技术产品运营经验。

mock测试常见的定义为:在测试过程中,对于某些不易构造或不易获取的对象,通过创建虚拟对象的方式来模拟测试的测试方法。

提到mock测试工具,java领域内可能首先想到的是Jmock、EasyMock、JMockit等。通常在单元测试中,由于对象、方法不是独立的,测试代码难以构造,所以业界提出了Mock Object技术来孤立被测试的对象。以上几种Mock 框架都限于一个Mock概念:即Mock Object 是用来代替与代码协作的对象的对象。和这几种框架一样,其他的 mock 框架也基本都局限于单元测试范畴,而在集成测试功能测试阶段还没有相应成熟的框架进行支持。所以本文提到的mock测试,更确切来说,是在功能测试阶段解决如何与外部系统间的数据交互。

文章结合本人所在的项目【秀品】来做相关介绍。大多用户直接接触到的只是秀品商城,但实际整个秀品业务系统的运转比较复杂,其中便涉及到和多个外部系统的对接及数据交互,比如仓储和物流都会和EMS、顺丰等有数据交互。而最近秀品开始涉及跨境业务,相应和电子口岸、境外的物流商等又会有数据交互。

当然,跟外部系统对接时系统间的联调测试必不可少,有些外部系统提供测试环境,有些甚至不提供。即便是提供测试环境的外部系统,一般也仅在开发联调阶段配合提供联调测试对接服务,一旦联调测试结束,也不再继续提供测试服务。那么,当这些外部系统的联调测试环境不可用时,我们就需模拟这些外部系统来和秀品系统进行数据交互,以便支持秀品完整业务测试流程的正常进行。针对这类mock测试需求,秀品QA做了几种实践,也是在实践中总结再改进的过程。

秀品系统采用的通信协议主要有:dubbo协议和http协议。和外部系统对接都是采用http协议,所以目前只需模拟外部系统对秀品系统的http请求回调功能。

以秀品和EMS(仓储物流商)的WMS(仓库管理系统)交互为例,EMS会提供一份标准对外接口文档给秀品。不同业务接口的调用形式和接口参数基本是一致的,仅通过参数值传递与业务相关的数据。约定如下图所示:

以其中一个WMS回传消息接口为例:【入库单收货确认回传接口】,其处理业务说明:WMS系统在入库单完成入库(上架)后,将对应入库信息回传给外部系统(即秀品)。EMS提供的文档说明如下图:

结合秀品系统实现,EMS的回调最终只需拼接成这样一个请求:

秀品某测试机Ip+http端口号+调用路径+servicename+appkey+content(xml格式)

其中:Ip+端口+调用路径+appkey 与测试环境配置相关,基本不随业务变化。

servicename+content(xml格式)和业务有关,频繁变化。

针对该【入库单收货确认回传接口】,则只需拼接并执行这样一个请求:

http://host:port/oms/wms/ems?service=WmsStockInConfirm&appkey=xxxxxx&content=< RequestReceiveInfo> xxxxxxxx</RequestReceiveInfo>

说明:content为上图中xml格式的数据集。

如何处理这类mock测试?

WAY1:寻找能发送http请求(get\post)的测试工具,例如fiddler、postman。

fiddler大家都比较熟悉,主要介绍下项目中使用的postman。Postman 是Chrome 扩展,提供功能强大的 Web API & HTTP 请求调试。它能够发送任何类型的HTTP 请求 (GET, HEAD, POST, PUT..),附带任何数量的参数+ headers。其具备两个主要优点:

1.能够保留历史请求,这样我们就可以很容易地重新发送请求;

2.有一个“集合(collection)”功能,用于存储所有请求相同的API/域。

使用效果如图:

Postman其实已足以满足大部分同类测试需求,且使用成本不高,不需额外编写测试代码。但结合我们项目特点,这些mock会影响每一次订单流程扭转的测试,使用频率非常高,且存在许多需要mock的回调接口。所以,针对这些影响可得出以下可改进点:

1.数据主要集中在xml中,每次执行需根据不同测试数据更改xml,改起来费时费力且易出错。

2.虽有“集合”功能,但一个人的测试集也不便于及时共享给其他同学。

3.操作界面虽有b格,但过于简陋,真心不便。

综合postman的优缺点,不如尝试把测试集固化到java代码里,因此开始了尝试WAY2:利用java代码,基于httpclient发送请求。类似于http接口测试,测试集代码如下图:

说明:

分别构造出请求url,xmlinfo及所需各参数后,执行请求即可。针对xml的处理,每次执行只需参照代码注释更改相应框内的属性值即可,减少编辑时间和出错概率,且一人写的代码其他同学都可以共用,总体还是提高了测试效率,基本满足了测试需求,但仍存有可改进点:

1.执行时要基于IDE,需要更改xml文件中相应属性值,同时必须具备代码运行环境。

2.没有可视化操作界面,存在使用门槛,操作不够方便。

如果传参更为简单,使用者无需接触测试代码,不用基于本地运行环境且能够可视化执行,这样可进一步提升测试效率,于是开始了尝试WAY3:模板语言在mock测试中的应用,并结合jenkisn实现用户界面。最便捷的方式首先想到了结合jenkins,通过运行jekins job,只需在可视化的界面里传入参数值,便可“一键执行”成功模拟出接口的回调,很好地解决待改进的问题。

针对该解决方案:

首先,测试代码需上传服务器,需解决服务器上构建打包的规范问题,以便可以通过命令行传入参数调用到不同测试类及模板文件。

其次,针对xml文件作为请求参数,考虑引入FreeMarker模板引擎,基于模板生成xml文件输出。提取出xml中在实际测试场景中需频繁更新的属性,重新定义成一个Java do类,向匹配的ftl文件传值。从而整体简化测试代码的繁锁度。

另外,从工具使用角度考虑,传参过多,也会较繁锁,所以考虑将输入的参数合并为长字符串,传递到程序后再做拆分处理。

总之,在设计代码结构及编写程序时,秉承着一个原则:尽可能通用化。

结合最终需拼接并执行的请求形式:

Ip+端口+调用路径+servicename+appkey+content(xml);

其中Ip+端口+调用路径+appkey 与测试环境配置相关,基本不变;

servicename+content(xml)和业务有关,频繁变化。

做了如下改进:

1.将请求url中环境配置相关的共通部分抽取,定义为CommonURLDo,以便可以灵活运行在不同的测试环境。

2.将不同业务接口(servicename)对应的xml定义为不同的ftl模板文件。并将模板需频繁变化的变量提取,定义成业务DO类,建立DO和ftl的映射,通过DO向ftl传参。

3.为测试类更通用,将ServiceName参数化,通过传入的ServiceName,渲染出相应的ftl模板文件。一个测试主类便可支持所有同类的需求。

4.最后,针对一个业务场景,配置相应jenkins job,传入三部分必需的参数:【测试类名】+【与环境配置相关的通用信息】+【xml文件需频繁变化的属性值】,执行job,便可完成一次回调模拟。

如图,代码结构组织及大体实现如下:

首先,定义ftl模板文件及相应DO。

其次,执行测试主类main方法,参数依赖于jenkins job执行传入,执行主要分为3个steps:

其中,step2中根据不同servicename调用不同业务处理类,实现如下:

最终,jenkins job的使用者界面如下:

借助于jenkins的用户界面,成功实现了“一键执行”。

那么,来运行一个mock测试试试吧~

至此,一个完整的mock测试场景已成功完成。

在自己编写和使用工具过程中,也会不断总结出一些待优化点,根据项目后续实际需要再做扩展。当然,现在这种方式仍有其局限性:

1.如果可以更通用,实现通用的mock server,client端使用时不需添加测试代码且有操作页面,只需在页面上进行简单配置便可成功执行测试;

2.能够以产品/项目维度对场景用例进行维护,共享并存储一份测试case,维护管理更便捷;

3.能够提供对多种协议的支持,例如http、dubbo、hessian等;

4.对自动化测试和性能测试的支持,提供自动化的API调用,甚至可以对一些压力测试场景提供支持。

如果可以实现一个通用mock测试平台,整体上将更利于测试效率的提升。

免费体验云安全(易盾)内容安全、验证码等服务

更多网易技术、产品、运营经验分享请点击

相关文章:
【推荐】 私有云爆发,未来增长空间巨大
【推荐】 kubernetes大概的工作原理
【推荐】 如何实现最佳的跨平台游戏体验呢?

mock测试方法及实践改进的更多相关文章

  1. 接口测试-Mock测试方法

    接口测试-Mock测试方法一.关于Mock测试1.什么是Mock测试?Mock 测试就是在测试过程中,对于某些不容易构造(如 HttpServletRequest 必须在Servlet 容器中才能构造 ...

  2. Gearman介绍、原理分析、实践改进

    gearman是什么? 它是分布式的程序调用框架,可完成跨语言的相互调用,适合在后台运行工作任务.最初是2005年perl版本,2008年发布C/C++版本.目前大部分源码都是(Gearmand服务j ...

  3. charles Mock测试总结

    转载:http://www.jianshu.com/p/03081c9d1559 1.背景 测试存在问题:1.测试环境接口不稳定2.业务系统不是孤立存在的,关联方太多,而且关联系统常常出现不稳定的情况 ...

  4. Spring Boot Mock单元测试学习总结

    单元测试的方法有很多种,比如使用Postman.SoapUI等工具测试,当然,这里的测试,主要使用的是基于RESTful风格的SpringMVC的测试,我们可以测试完整的Spring MVC流程,即从 ...

  5. 白盒测试实践项目(day6)

    胡俊辉负责JUint测试部分,了解JUint测试的方法,并对其他成员介绍JUint的使用,负责JUnit部分相关文档的编写,负责博客园博客的维护,负责小组成员的任务分类与管理. 李建文负责代码复审部分 ...

  6. 白盒测试实践项目(day3)

    李建文同学的白盒缺陷报告已经提交,正在由组长胡俊辉同学进行审阅,查看并发现是否有什么不足,再由小组讨论补充. 汪鸿同学的静态代码工具熟悉已经初步完成,并且准备撰写文档. 杨瑞丰同学的Mock测试方法也 ...

  7. Jmockit使用

    引用单元测试中mock的使用及mock神器jmockit实践中的java单元测试中各种Mock框架对比,就能明白JMockit有多么强大: JMockit是基于JavaSE5中的java.lang.i ...

  8. Y事业部打造一体化质量管理平台

    互联网企业质量管理的困惑 作为互联网时代的互联网企业,我们的研发模式和传统模式相比,最显著的不同在于发布节奏加快了,这个加快不是快了10%,20%,50%,而是加快了几倍,甚至几十倍,上百倍.面对加快 ...

  9. 京东Y事业部打造一体化质量管理平台

    互联网企业质量管理的困惑 作为互联网时代的互联网企业,我们的研发模式和传统模式相比,最显著的不同在于发布节奏加快了,这个加快不是快了10%,20%,50%,而是加快了几倍,甚至几十倍,上百倍.面对加快 ...

随机推荐

  1. Django一对多的创建

    1.一对多的应用场景: 例如:创建用户信息时候,需要选择一个用户类型[普通用户][金牌用户][铂金用户]等. 2.方法: class Business(models.Model): buss=mode ...

  2. cocos2d-x中对象的位置,旋转,缩放

    版权声明:本文为博主原创文章,未经博主同意不得转载. https://blog.csdn.net/cuit/article/details/26729633 分为两种: 缓动.IntervalActi ...

  3. 《高性能Javascript》 Summary(三)

    第八章.编程实践 Programming Practices 经验: 避免使用 eval_r()和Function构造器避免二次评估.此外,给setTimeout()和setInterval()函数传 ...

  4. 《高性能Javascript》 Summary(二)

    第四章.算法和流程控制 Algorithms And Flow Control 原因:代码整体结构是执行速度的决定因素之一.代码量少不一定运行速度快,代码量多不一定运行速度慢.性能损失与组织代码和具体 ...

  5. Android Weekly Notes Issue #275

    Android Weekly Issue #275 September 17, 2017 Android Weekly Issue #275 本期内容包括给Google Map实现一个Marker A ...

  6. 用vector代替实现二维数组

    vector可以用来模拟数组,当然也可以用来模拟二维数组: 定义如:vector<int>a[100];   相当于定义了一个100行的数组,当每行的大小是不确定的 模板应用如下: #in ...

  7. sping junit test

    @ContextConfiguration(locations="classpath:spring.xml")public class BaseTest extends Abstr ...

  8. 线上cpu100%问题快速定位

    问题描述:服务器上部署了多个tomcat,即垂直切分的Web站点,记忆多个Java微服务,突然收到运维的cpu异常告警. 步骤一:找到最耗cpu的进程 工具:top 方法: 执行top -c,显示进程 ...

  9. Cocos2d-x中单例的使用

    大家都知道一个程序中只有一个导演类,eg: CCDirector *pDirectory = CCDirector::sharedDirector();//初始化导演类. 可通过 pDirectory ...

  10. 使用谷歌浏览器进行Web开发技巧

    1.为了避免缓存影响开发,使用使用那个“Ctrl+Shift+N”进入浏览器的隐身模式