1、Wiremock工具介绍

一般开发项目都会分模块进行,比如都会把前端和后端分开,在前端和后端里面也通常是分模块开发的。当开发进度不一致时,可以对依赖接口构建Mock Service,模拟不同输入/数据/场景,这样不至于影响本模块的开发进度。构建Mock Service方法很多,今天介绍Wiremock,Wiremock非常轻便易用,甚至不用编程,一个jar包基本够用了,当然,也可以把它引用写进测试代码里。

官网地址:http://wiremock.org/

Jar包下载:http://repo1.maven.org/maven2/com/github/tomakehurst/wiremock-standalone/2.1.10/wiremock-standalone-2.1.10.jar

2、Wiremock工作原理

启动wiremock

java -jar wiremock-2.1.10-standalone.jar –port 9999 —verbose
  • 1

(–port设定端口为9999; –verbose开启日志。更多参数需要参考: 
http://wiremock.org/docs/running-standalone/ 
启动后在同目录下生成两个空的文件夹:__files和mappings。__files是放上传/下载/录制文件的,mappings放response和request url的映射的。 
在mappings文件夹下随便创建一个*.json文件,比如长下面这样:

"request": {"method": "GET","url": "/api/testdetail"},"response": {"status": 200,"bodyFileName": "testdetail.json”, "headers": {"Content-Type": "application/json","Cache-Control": "max-age=86400"}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

bodyFileName还可以是html、xml等文档。 
在浏览器或者使用curl命令,调用http://localhost:9999/api/testdetail,就能返回testdetail.json的内容了。testdetail.json就是需要我们在__files里面建立的响应文件。wiremock也支持直接在response结构体中返回响应内容,比如在mapping文件中,将response写成下面这样:

"response": {"status": 200,"body": “Hello world ","headers": {"Content-Type": "application/json","Cache-Control": "max-age=86400"}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

当发送请求时候,将直接返回“Hello world”。

3、Wiremock支持的HTTP方法

HTTP方法支持GET, POST, PUT, DELETE, HEAD, TRACE, OPTIONS等,自定义头、数据模板(bodyPatterns,如不符合,抛出404错误),URL Template,Query参数匹配,显示指定文件内容等。下面将介绍如何使用wiremock实现这些。

3.1 POST

POST http://localhost:9999/api/products


{"request": {"method": "POST","url": "/api/products","bodyPatterns": [{"equalToJson" : "{ \"name\": \"new product\", \"creator\": \"tester\", \"createTime\": \"2015-09-07\" }", "jsonCompareMode": "LENIENT"}]},"response": {"status": 201,"body": "Add successfully.","headers":{"x-token":"xxxxxxxxxxxxxxxxxxxxxxxxxxxx"}}}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

3.2 PUT

PUT: http://localhost:9999/api/products/1

{"request": {"method": "PUT","url": "/api/products/1","bodyPatterns": [{"equalToJson": "{ \"id\": 1, \"name\": \"new product\", \"creator\": \"tester\", \"createTime\": \"2015-09-07\" }","jsonCompareMode": "LENIENT"}]},"response": {"status": 200,"body": "Update successfully.","headers": {"x-token": " xxxxxxxxxxxxxxxxxxxxxxxxxxxx"}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

3.3 DELETE

DELETE: http://localhost:9999/api/products/1


{"request": {"method": "DELETE","url": "/api/products/1" },"response": {"status": 204,      "headers":{"x-token":" xxxxxxxxxxxxxxxxxxxxxxxxxxxx"}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3.4 URL Matching

URL Matching: http://localhost:9999/api/products/1(2/3…)

{"request": {"method": "GET","urlPattern": "/api/products/[0-9]+"},"response": {"status": 200}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

3.5 Query参数匹配

Query参数匹配:http://localhost:9999/api/products?search=china

{"request": {"method": "GET","urlPath": "/api/products","queryParameters": {"search": {"contains": "chin"}}},"response": {"status": 200,"headers": {"Content-Type": "application/json"},"body": "{ \"id\": 7, \"name\": \"shan zai\", \"from\":\"China\" },{ \"id\": 7, \"name\": \"shan zai\", \"from\":\"China(RPC)\" }"}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

3.6 模拟错误

模拟404错误


{"request": {"url": "/unknown.html","method": "GET"},"response": {"status": 404,"headers": {"Content-Type": "text/html; charset=utf-8"}}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

3.7 设置响应延迟

{"request": {"method": "GET","url": "/delayed"},"response": {"status": 200,"bodyFileName": "mytest.json","headers": {"Content-Type": "application/json","Cache-Control": "max-age=86400"},"fixedDelayMilliseconds": 2000}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

4、Mock Service平台化

使用WireMock通过mappings和__files文件夹可以有效管理映射和返回内容文件。而这两个文件目前是手动编辑,如果可以做成平台化管理,所有接口通过创建完成,文件命名规则全部由系统进行管理,将节省的时间更多投入业务关注和及早进行自测,这样子的收益将会更大。

那怎么样的平台才算能够满足当前需求呢?

基于HTTP协议 
支持Url、UrlPattern匹配、Query参数 
支持数据存储 
API接口规范化管理 
提交表单即可生成mapping和__files所需文件 
不同项目接口有不同的前缀 
能够返回指定格式(json、xml、html等)内容 
能够设定响应延迟 
设置cookies 
设置headers 
支持用户验证

根据需求设计总体架构如下: 
包括前台和后台。前台负责接受用户的Mock设置,后台负责将用户的设置转换为WireMock所需要的mapping和__file文件,并提供查询功能。 
MockServer架构图 
 
根据架构图,做了总体设计如下: 
 
页面分为Mock项目管理和Mock API管理。Mock项目管理可以创建、修改、删除Mock项目,Mock PAI管理可以创建、修改、删除Mock的API。后台管理负责生成mapping和file文件、对wiremock进行重启等。

4.1 技术选型

由于大家对python都比较熟悉,也有过使用python的Flask框架进行开发经验,这次依然采用Flask+Mysql的方案。从界面录入到mapping、_files文件生成处理采用Python,后台工具使用WireMock的standalone模式,通过shell脚本进行一键启停管理,以及实时刷新url、mapping映射。

4.2 Mock项目管理页

4.2.1 添加项目

配置协议、进行mock服务器的重启、重新加载(有新的mapping、file文件生成系统会自动reset即可,当然手工reset也可以,即时加载无须重启服务等待)。 

4.2.2 显示项目

4.2.3 修改项目

4.2.4 删除项目

4.3 Mock API管理页

4.3.1 添加API

选择方法、URL类型,填写URL(如果选择URL类型为UrlPattern,则填写正则表达式),填写状态码、返回接口,以及返回头,就可以完成一个mock接口的创建。这些信息要存储到Mysql。 
 
1)手工输入 
适合响应体比较短小的情况 
 
2)通过url获取 
返回体比较大,目标Mock接口已经存在,可以直接抓取生成文件; 
 
3)上传文件的方式 
返回体比较大、目标Mock接口还未开发完成,手工上传返回内容的文件即可。 
 
以上三种灵活的保存返回内容方式,最终保存的接口会按照以下格式生成mapping和__files所需文件。 

4.3.2 显示API

展示列表,列出相关URL、方法、是否正则、返回码、返回类型。 

4.3.2 修改API

4.3.3 删除API

4.4 MockServer后台

使用Java-WireMock进行后台服务,在项目配置页通过按钮:重启、重新加载,调用后台脚本:wiremock_controller.sh,脚本内容参考:

#!/bin/bash
if [ "$#" = 0 ];thenecho "Usage: $0 (start|stop|restart|reset)"exit 1
fidirWiremock=`pwd`
getCount=`ps -ef | grep "wiremock-1.53-standalone" | grep -v "grep" |wc -l`
wiremock_jar=${dirWiremock}/wiremock-1.53-standalone.jar
port=9999
wiremock_url=http://localhost:${port}stop(){count=${getCount}if [ 1==${count} ];thencurl -d log=aaa ${wiremock_url}/__admin/shutdownecho "Stop success!......"elseecho "Already stop"fi
}start(){count=${getCount}if [ 0==${count} ];thennohup java -jar ${wiremock_jar} --verbose=true --port=${port} &    echo "Start success!......"elseecho "Already start"fi
}if [ "$1" = "restart" ];thencount=${getCount}if [ 1==${count} ];thenecho "Wiremock is running,wait for restarting! ...."stop  echo "Start wiremock......"start  elsestartfielif [ "$1" = "start" ];thenecho "Start wiremock......"startelif [ "$1" = "stop" ];thenecho "Stop wiremock......"stopelif [ "$1" = "reset" ];thencount=${getCount}if [ 0==${count} ];thenecho "Wiremock must be running before reset,wait for starting! ...."startficurl -d log=aaa  ${wiremock_url}/__admin/mappings/resetecho "Reset success!......"
fi
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60

其中: 
“nohup java -jar wiremockjar−−verbose=true−−port=wiremockjar−−verbose=true−−port={port} &”:在linux系统后台运行WireMock; 
“curl -d log=aaa ${wiremock_url}/__admin/mappings/reset”:是通过发送POST请求,重新加载新生成的配置文件。

5、总结

Mock API接口是非常必要的,因为不同研发组的系统之间的数据交互往往是通过接口来实现,当不同组接口开发不同步时,接口测试无法及早参与,对接调试比较困难。这样势必导致软件开发迭代变慢,没有时间对质量进行充分验证。 
可以借鉴《自动化单元测试实践之路》在单元测试中,使用Mockito对依赖进行Mock,那同样道理,使用Mock技术也可以对HTTP API进行Mock,按照这个思路探索下去,看看有没有开源解决方案,是否能够解决当前问题,如果可以就不用重复写一套解决方案;如果不行,那能否基于开源的做二次开发呢?

6、参考文档

http://wiremock.org/docs/ 
http://www.infoq.com/cn/articles/evolution-of-httpservermock-from-hand-to-platform/

基于Wiremock创建Mock Service平台相关推荐

  1. 如何在 SAP BTP 平台 ABAP 编程环境里消费基于 SOAP 的 Web Service

    这是 Jerry 2021 年的第 47 篇文章,也是汪子熙公众号总共第 324 篇原创文章. Jerry 2014 年时,曾经在 SAP 社区上写过一篇英文博客,介绍了如何在 ABAP On-Pre ...

  2. 我的WCF之旅(13):创建基于MSMQ的Responsive Service

    一.One-way MEP V.S. Responsible Service 我们知道MSMQ天生就具有异步的特性,它只能以One-way的MEP(Message Exchange Pattern)进 ...

  3. JeecgBoot 2.4 微服务正式版发布,基于SpringBoot的低代码平台

    项目介绍 JeecgBoot 是一款基于代码生成器的低代码平台!前后端分离架构 SpringBoot2.x,SpringCloud,Ant Design&Vue,Mybatis-plus,Sh ...

  4. [转]基于SQL Server 2008 Service Broker构建企业级消息系统

    http://www.infoq.com/cn/articles/enterprisemessage-sqlserver-servicebroker 1.引言 Microsoft 在SQL Serve ...

  5. 基于Springboot的特产销售平台设计与实现毕业设计源码091036

    Springboot特产销售平台的设计与实现 摘 要 近年来,随着移动互联网的快速发展,电子商务越来越受到网民们的欢迎,电子商务对国家经济的发展也起着越来越重要的作用.简单的流程.便捷可靠的支付方式. ...

  6. 构建基于openEuler2209的OpenStack云平台(十一)

    上一篇:构建基于openEuler2209的OpenStack云平台(十) 11 安装和配置Heat服务(Orchestration service) Heat服务(Orchestration ser ...

  7. 基于Web的校园互助平台设计与实现

     其他项目,点击作者主页   目录 1 系统简介 2 系统相关技术 3 需求分析 3.1系统概述 3.2系统业务流程分析 3.3系统各模块功能需求分析 3.3.1用户端功能需求分析 ​​​​​​​3. ...

  8. 基于Springboot的书籍学习平台

    摘要 首先,论文一开始便是清楚的论述了平台的研究内容.其次,剖析平台需求分析,弄明白"做什么",分析包括业务分析和业务流程的分析以及用例分析,更进一步明确平台的需求.然后在明白了平 ...

  9. 基于JavaWeb的健康管理平台-源码+论文

    今天介绍的项目是基于JavaWeb的健康管理平台, 主要内容如下 1.1 设计背景 紧张的工作节奏.教学和科研的压力.个人不良的工作生活习惯.以及伴随工作压力而来的家庭关系.人际关系紧张等因素使得高校 ...

  10. php家教服务系统,基于PHP技术家教信息平台的设计与实现

    2017 年 6 月 25 日第 1 卷 第 1 期 现代信息科技 Modern Information Technology Jun.2017 Vol.1 No.1 272017.6 基于 PHP ...

最新文章

  1. DeepMind“钓鱼执法”:让AI引诱AI说错话,发现数以万计危险言论
  2. Socket网络编程笔记
  3. 深入ASP.NET数据绑定(中)——数据双向绑定机理
  4. Android中Intent/Bundle的通信原理及大小限制(Parcelable原理及与Serializable的区别)
  5. [Leedcode][JAVA][第9题][回文数][数学法]
  6. java 异步_聊聊java高并发系统之异步非阻塞
  7. Vue 3.0没有config文件解决方法
  8. python写梦幻西游手游脚本辅助_GitHub - Sandry666/mhxy_fz: 一个基于计算机视觉开发的梦幻西游辅助脚本...
  9. scrapy提高爬取速度
  10. WTL 自绘控件库 (CQsAnimaStatic)
  11. 友链——一群dalao
  12. 查找网站的IP地址的两种方法
  13. 用上office365后配合RaiDrive效率如何提高
  14. Python 爬虫教学网站
  15. poi3.17版本生成excel文件时,单元格生成求和公式
  16. 基于Adaboost的高光谱分类算法设计
  17. 有知群产品经理必修TOP班学习笔记
  18. 一维向量转换为n维向量_如何在N维上固定万向节锁
  19. lut预设安装:LUTs预设如何导入pr?lut预设导入Premiere Pro教程
  20. 3GPP25.321中HSDPA的Mac-hs实体研究

热门文章

  1. 阶段1 语言基础+高级_1-3-Java语言高级_05-异常与多线程_第2节 线程实现方式_11_Thread类的常用方法_sleep...
  2. CPU Usage (C#) 测试
  3. how-to-set-java_home-environment-variable-on-mac-os-x
  4. Python 线程 进程 协程
  5. 在idea或eclipse软件下配置Tomcat
  6. 程序员职业规划(一篇来自阿里Java工程师对工作3年左右程序员的职业建议和应该掌握的职业技能)...
  7. Mybatis-generator自动生成
  8. 洛谷 P1025 数的划分
  9. 如何在ADO中使用数据读取器(DataReader)读取数据
  10. Spring学习笔记17--在XML中使用SPEL