转载自 https://tech.meituan.com/mock-server-in-action.html

背景

在美团服务端测试中,被测服务通常依赖于一系列的外部模块,被测服务与外部模块间通过REST API或是Thrift调用来进行通信。要对被测服务进行系统测试,一般做法是,部署好所有外部依赖模块,由被测服务直接调用。然而有时被调用模块尚未开发完成,或者调用返回不好构造,这将影响被测系统的测试进度。为此我们需要开发桩模块,用来模拟被调用模块的行为。最简单的方式是,对于每个外部模块依赖,都创建一套桩模块。然而这样的话,桩模块服务将非常零散,不便于管理。Mock Server为解决这些问题而生,其提供配置request及相应response方式来实现通用桩服务。本文将专门针对REST API来进行介绍Mock Server的整体结构及应用案例。

名词解释

  • Mock规则:定义REST API请求及相应模拟响应的一份描述。
  • Mock环境:根据请求来源IP来区分的Mock规则分组。Mock Server可以定义多套Mock环境,各套环境间相互隔离。同一个IP只能对应一个Mock环境,不同的IP可以对应同一个Mock环境。

整体结构

Mock Server由web配置页面Mock Admin及通用Mock Stub组成:Mock Admin提供了web UI配置页面,可以增加/删除请求来源IP到Mock环境的映射,可以对各套环境中的Mock规则进行CRUD操作;Mock Stub提供通用桩服务,对被测系统的各类REST API请求调用,返回预先定义好的模拟响应。为了提高桩服务的通吐,使得桩服务能在被测系统压力测试中得到好的表现,我们开启了5个桩服务,通过Nginx做负载均衡。Mock Server的整体结构如下图所示。

数据存储

  • 将请求来源IP到Mock环境名的映射存储到mock-env.conf中,mock-env.conf的每一行定义了一条映射,如:
    192.168.3.68 闫帅的测试机环境
    这条映射表明来源是192.168.3.68的请求,使用Mock环境名为闫帅的测试机环境的Mock规则。
  • 将配置的Mock规则存放到<对应Mock环境名>.xml中,下面部分展示了Mock规则的存储格式。
<configuration>
...
<mock id="716add4f-33f7-49ac-abf3-fc617712ffea" name="test001" author="yanshuai">
<request>
<uri>/api/test/.*</uri>
<method>GET|POST|PUT|DELETE</method>
<parameters>
<parameter name="name" value="test.*"/>
...
</parameters>
<headers>
<header name="nb_deviceid" value="1E[0-9a-zA-Z]+"/>
...
</headers>
</request>
<response delay="1000" real="false">
<statusCode>200</statusCode>
<format>application/json;charset=UTF-8</format>
<customHeaders>
...
</customHeaders>
<body>{&quot;name&quot;:&quot;闫帅&quot;}</body>
</response>
</mock>
...
</configuration>

Mock Stub

当请求发送到Mock Stub时,Mock Stub会根据请求的来源IP找到对应的独立环境名,然后根据独立环境名获取所有预定义的Mock规则,遍历这些Mock规则,如果找到一条规则与接受到的请求匹配,那么返回预定义的模拟响应。如果找不到规则匹配,那么返回404错误。其中,规则匹配是根据请求中的uri/method/headers/parameters/body是否与Mock规则中定义的对应字段正则匹配来定的。

Mock Admin

  • 打开Mock Admin配置页面,如果尚未映射来源IP地址到环境,则点击环境列表导航链接,进入环境列表页面,点击添加,输入源IP及环境名,点击确定按钮,实现源IP到所设环境的映射。

  • 点击规则列表,规则列表页面将默认罗列出default环境的所有Mock规则(如“语音登录code获取”规则)。重新选择环境,可以罗列出所选环境中的Mock规则。每个Mock规则都处于详细信息展开的状态。点击“全部折叠”按钮,将把所有的规则详细信息给隐藏;点击“全部展开”按钮,将把所有的规则详细信息给展开。点击“只显示本人创建的规则”,将过滤得到mis账户用户创建的规则。点击“按创建时间排序”的开关按钮,将实现Mock规则的升序/降序显示。
  • 点击导航栏的“新建规则”选项,可以创建一个Mock规则,需要填写规则名称、请求及响应,并选中环境。对于请求,需要填写URL及勾选Method,如果要求对于符合某种规则的请求才被Mock,则填写对应的Headers/Parameters/Body Like,这些数据都是正则匹配的形式。对于响应,如果勾选了“返回真实响应”,则只需要关注延时(延时是指返回请求需要的sleep时间,单位是毫秒)。此时需要将请求的URL地址给写完整了,需要包含host(IP)及port,不能只是path。如果不勾选“返回真实响应”,则将返回模拟响应。Status Code填写返回码,比如200,404;Format选择返回数据的格式,比如json,html等;还可以返回自定义的Headers及响应的Body。点击新建按钮以后,如果创建成功,则提示成功创建,并跳转到规则列表页面。
  • 对于一个创建好的Mock规则,可以点击Action下拉菜单,进行操作。如果点击“克隆”,则跳转到“新建规则”页面,并将克隆的Mock规则信息给填充进去;点击“编辑”,则跳转到更新页面,更新页面填充了要编辑的Mock规则信息;点击“删除”,则弹出确认删除对话框,点击确定按钮,将删除此规则;点击取消按钮,则取消删除操作。如果此Mock规则处于详细信息展开状态,则可点击折叠来隐藏详细信息;如果处于详细信息折叠状态,则可点击展开选项,将显示详细信息。上移选项,可以将Mock规则上移一位;下移选项,可以将Mock规则下移一位。

使用方式

  1. 修改被测服务的HTTP依赖,将依赖的IP和端口分别设置为mock.ep.sankuai.com和80,并重启被测服务;
  2. 创建Mock规则;
  3. 调用被测服务的API,被测服务将调用Mock服务;
  4. 删除Mock规则(可选)。

编程使用

创建/删除Mock规则,除了可通过Mock Admin页面配置外,Mock Server还提供了SDK方式,用户可以通过编码来使用Mock Server。

  • 在Maven工程pom.xml中添加mock-client依赖
<dependency>
<groupId>com.sankuai.meituan.ep.mockserver</groupId>
<artifactId>mock-client</artifactId>
<version>1.0.6</version>
</dependency>
  • 创建/删除Mock规则
// 构造Mock规则
MockRule rule = new MockRule();
rule.setMockName("test-" + System.currentTimeMillis()); // Mock name必须设置
rule.setAuthor("yanshuai"); // author必须设置,设置为代码编写者的mis账号前缀,比如lining03
MockRequest mockRequest = new MockRequest();
mockRequest.setUri("/api/test/" + System.currentTimeMillis()); // Mock请求的uri必须设置
/**
* Mock请求的方法必须设置
* 如果只有GET请求,则写成GET;
* 如果有GET请求及PUT请求,则写成GET|PUT;
* 即用|分割请求方法,不能有空格。
*/
mockRequest.setMethod("POST|GET");
// 必要的话,设置Mock请求的匹配header
List<MockRequestHeader> mockRequestHeaders = new ArrayList<MockRequestHeader>();
mockRequestHeaders.add(new MockRequestHeader("device", "android2.3"));
mockRequest.setHeaders(mockRequestHeaders);
// 必要的话,设置Mock请求的匹配参数
List<MockRequestParameter> mockRequestParameters = new ArrayList<MockRequestParameter>();
mockRequestParameters.add(new MockRequestParameter("wd", "123.*"));
mockRequestParameters.add(new MockRequestParameter("version", "v1"));
mockRequest.setParameters(mockRequestParameters);
rule.setMockRequest(mockRequest);
MockResponse mockResponse = new MockResponse();
mockResponse.setDelay(1000L); // 设置Mock响应的延时
mockResponse.setStatusCode(200); // 设置Mock响应的状态码
/**
* 设置Mock响应的格式
* 如果是json返回,则为application/json;charset=UTF-8;
* 如果是文本返回,则为text/plain:charset=UTF-8;
* 如果是xml返回,则为text/xml;charset=UTF-8;
* 如果是html返回,则为text/html;charset=UTF-8。
*/
mockResponse.setFormat("application/json;charset=UTF-8");
List<MockResponseHeader> mockResponseHeaders = new ArrayList<MockResponseHeader>(); // 设置Mock响应的header
mockResponseHeaders.add(new MockResponseHeader("customHeaderName", "customHeaderValue"));
mockResponse.setMockResponseHeaders(mockResponseHeaders);
mockResponse.setBody("{\"code\":200}"); // 设置Mock响应的body
rule.setMockResponse(mockResponse); // 创建Mock规则
final MockClient client = new MockClient();
String id = client.addRule("default", rule); // default为环境名,如果使用别的环境,则填写别的环境名 // 调用被测服务的API,被测服务将调用Mock服务
// 省略调用代码... // 删除Mock规则
client.removeRule("default", id); // default为环境名,如果使用别的环境,则填写别的环境名

典型案例

  1. 相同Mock环境,同一接口,不同参数,可以有不同的Mock结果
    按照下图,依次创建这两条规则(顺序相关),然后在default环境对应的机器上,访问http://mock.ep.sankuai.com/user/v1/info?token=fake,返回{"code":401,"type":"sys_err_auth_fail","message":"invalid token"};访问http://mock.ep.sankuai.com/user/v1/info?token=other,返回{"user": {"id": 29008301,"mobile": "15001245907","isBindedMobile": 1}}。


  2. 真实请求延时Mock
    按照下图创建规则,在闫帅的测试机环境对应的机器上,访问http://mock.ep.sankuai.com/api/v1/divisions,将延迟5s返回城市列表json串。
  3. 不同Mock环境,完全相同的接口参数,可以有不同的Mock结果
    按照下图创建规则,在闫帅的测试机环境对应的机器上,访问http://mock.ep.sankuai.com/cachier/paynotify返回值是failure;在支付php环境对应的机器上,访问http://mock.ep.sankuai.com/cachier/paynotify返回值是success。

 
 
http://www.mock-server.com/where/downloads.html
 
 
1

Mock Server实践的更多相关文章

  1. 基于django rest framework的mock server实践

    网上找了一下mock server的实现,发现python的基本都是基于flask来实现的,因最近在学django,就尝试用drf实现了下: A brief introduction of sui_m ...

  2. mock server相关解决方案

    前后端分离之后 前后端分离后, 大家从此进入了所谓的并行开发时代. 一旦完成前后端的(边界)分工, 大家就可以各司其职了. 前端在与后端交互时, 要想有效地提高工作效率, 后端的接口文档就是重中之重了 ...

  3. 关于mock server

    这篇技术博客是在知乎上看到的 知乎js大神张云龙写的 这里贴过来记录下,如果侵权 请告知将及时删除. --------------------------- 为了更好的分工合作,让前端能在不依赖后端环 ...

  4. Fiddler-009-AutoResponder 简单的 MOCK SERVER 应用实例

    在我们日常的测试中经常需要测试特定的响应对应的客户端展示样式是否正确无误,实现测试方法一般有如下三种: 创建新的测试数据(工作量较大) 修改已有测试数据(例如修改对应的状态码,若是最终需要测试的按钮状 ...

  5. mock server 前后端分离小结(转)

    1.前台开发受限于后台开发的速度 2.后台提供给前台的接口缺字段,时常需要联调 基于Mock Server开发的好处: 对于前端来讲,可以独立于后端进行开发. 对于后端来讲,根据前端定义的接口进行开发 ...

  6. 基于moco的mock server 简单应用 来玩玩吧

    提起mock大家应该就知道是干嘛用的了,再次再介绍一种简单的方式,基于moco的mock server.步骤很简单: 1. 首先,要下载个moco的jar0_1482402640757_moco-ru ...

  7. Mock Server 入门

    Mock Server介绍 什么是mock ? 我在去年的时候介绍一篇幅 python mock的基本使用,http://www.cnblogs.com/fnng/p/5648247.html 主要是 ...

  8. Mock Server文章链接

    Mock Server文章链接 2017-06-14 1 Dreamhead (Zheng Ye) Moco可以提供以下服务: HTTP APIs Socket APIs REST API GitHu ...

  9. Postman Mock Server

    为了不影响前端开发的进度,一般后端都是先定数据结构,然后写个假接口让前端调用,这样前端就不必等着后端接口开发完成以后再开始了.届时,前后端以及UI和测试就可以并行,待双方都把各自的逻辑写好了,便可以联 ...

随机推荐

  1. c++11新特性之宽窄字符转换

    C++11增加了unicode字面量的支持,可以通过L来定义宽字符:str::wstring str = L"中国人": 将宽字符转换为窄字符串需要用到codecvt库中的std: ...

  2. OneNote如何使用

    自从安装了Office2013后发现office套件中有很多的好东西,今天要和大家分享的就是Office套件中的OneNote软件,这狂软件能够很方便的记录我们生活中的一些学习资料.一些决绝方法的经验 ...

  3. ASP.NET 线程详解

    本文是博主翻译文章,估计会省略一些,但是我尽量能翻译好,各个知识点通俗易懂.译文如下: ASP.NET Thread Usage on IIS 7.5, IIS 7.0, and IIS 6.0 我简 ...

  4. 关于fpga的m9k的部分理解

    1.控制信号包括时钟使能,读写使能,字节使能,地址使能,异步清零等 2.可配置为单端口,简单双端口,真双端口,fifo,rom,移位寄存器. 3.关于移位寄存器模式的介绍如下: 一个 ( w × m ...

  5. AES前后加密算法代码

    首先下载aes.js加密工具类: 本文采用的是 AES/ECB/PKCS5Padding的加密方式进行加密的: js加密写法如下: <!DOCTYPE html> <html lan ...

  6. redis的安装和类型及基本命令

    一.memcached和redis区别 1. redis 可以存储,memcached用来缓存, 2. 数据类型,memcached只有string:redis有string,链表,哈希结构,集合,有 ...

  7. 使用FormData实现ajax文件异步上传

    1.传统的web开发文件上传一般是基于form表单的文件上传,同步的方式,用户体验差,可控性也差 2.异步上传的实现 有以下方式 2.1 借助浏览器插件 一般需要安装一些类似flash的插件  这种方 ...

  8. selenium之 chromedriver与chrome版本映射表

    看到网上基本没有最新的chromedriver与chrome的对应关系表,便兴起整理了一份如下,希望对大家有用: chromedriver版本 支持的Chrome版本 v2.40 v66-68 v2. ...

  9. AngularJS:表格

    ylbtech-AngularJS:表格 1.返回顶部 1. AngularJS 表格 ng-repeat 指令可以完美的显示表格. 在表格中显示数据 使用 angular 显示表格是非常简单的: A ...

  10. 异步fifo的读写

    这里不讨论异步fifo是如何实现的,而是在实现fifo的前提下,对fifo的读写. 现在遇到的问题是:总线的数据不能写入fifo中,但是地址能加一. 代码如下: if( !fifo_tx_full & ...