转载:http://blog.csdn.net/liuchunming033/article/details/52399397

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"
}
}
}

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"
}

当发送请求时候,将直接返回“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"
}
} }

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"
}
}
}

3.3 DELETE

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


{
"request": {
"method": "DELETE",
"url": "/api/products/1"
},
"response": {
"status": 204,
"headers":{
"x-token":" xxxxxxxxxxxxxxxxxxxxxxxxxxxx"
}
}
}

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
}
}

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)\" }"
}
}

3.6 模拟错误

模拟404错误


{
"request": {
"url": "/unknown.html",
"method": "GET"
},
"response": {
"status": 404,
"headers": {
"Content-Type": "text/html; charset=utf-8"
}
}
}

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
}
}

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 ];then
echo "Usage: $0 (start|stop|restart|reset)"
exit 1
fi dirWiremock=`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} ];then
curl -d log=aaa ${wiremock_url}/__admin/shutdown
echo "Stop success!......"
else
echo "Already stop"
fi
} start(){
count=${getCount}
if [ 0==${count} ];then
nohup java -jar ${wiremock_jar} --verbose=true --port=${port} &
echo "Start success!......"
else
echo "Already start"
fi
} if [ "$1" = "restart" ];then
count=${getCount}
if [ 1==${count} ];then
echo "Wiremock is running,wait for restarting! ...."
stop
echo "Start wiremock......"
start
else
start
fi elif [ "$1" = "start" ];then
echo "Start wiremock......"
start elif [ "$1" = "stop" ];then
echo "Stop wiremock......"
stop elif [ "$1" = "reset" ];then
count=${getCount}
if [ 0==${count} ];then
echo "Wiremock must be running before reset,wait for starting! ...."
start
fi
curl -d log=aaa ${wiremock_url}/__admin/mappings/reset
echo "Reset success!......"
fi

其中: 
“nohup java -jar 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. 基于Wiremock创建Mock Service平台(转)

    本文链接:https://blog.csdn.net/liuchunming033/article/details/52399397                                   ...

  2. 用C#基于WCF创建TCP的Service供Client端调用

    本文将详细讲解用C#基于WCF创建TCP的Service供Client端调用的详细过程 1):首先创建一个Windows Service的工程 2):生成的代码工程结构如下所示 3):我们将Servi ...

  3. Govern Service 基于 Redis 的服务治理平台

    Govern Service 基于 Redis 的服务治理平台(服务注册/发现 & 配置中心) Govern Service 是一个轻量级.低成本的服务注册.服务发现. 配置服务 SDK,通过 ...

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

    注:这篇文章是为InfoQ 中文站而写,文章的地址是:http://www.infoq.com/cn/articles/enterprisemessage-sqlserver-servicebroke ...

  5. 如何使用新浪微博账户进行应用登录验证(基于Windows Azure Mobile Service 集成登录验证)

    使用三方账号登录应用应该对大家来说已经不是什么新鲜事儿了,但是今天为什么还要在这里跟大家聊这个话题呢,原因很简单 Windows Azure Mobiles Service Authenticatio ...

  6. 【转】基于CXF Java 搭建Web Service (Restful Web Service与基于SOAP的Web Service混合方案)

    转载:http://www.cnblogs.com/windwithlife/archive/2013/03/03/2942157.html 一,选择一个合适的,Web开发环境: 我选择的是Eclip ...

  7. 基于HttpRunner的接口自动化测试平台HttpRunnerManager(二)

    https://github.com/HttpRunner/HttpRunnerManager HttpRunnerManager Design Philosophy 基于HttpRunner的接口自 ...

  8. Web Service平台概述

    Web  Service平台主要涉及的技术有SOAP(Simple  Object  Access  Protocal,简单对象访问协议), WSDL(Web  Service  Descriptio ...

  9. 基于JAX-WS的Web Service服务端/客户端 ;JAX-WS + Spring 开发webservice

    一.基于JAX-WS的Web Service服务端/客户端 下面描述的是在main函数中使用JAX-WS的Web Service的方法,不是在web工程里访问,在web工程里访问,参加第二节. JAX ...

随机推荐

  1. VS 2013插件

    http://www.spersky.com/post/vsPlugins.html http://vswebessentials.com/download http://developer.51ct ...

  2. cf 843 A Sorting by Subsequences [建图]

    题面: 传送门 思路: 这道题乍一看有点难 但是实际上研究一番以后会发现,对于每一个位置只会有一个数要去那里,还有一个数要离开 那么只要把每个数和他将要去的那个位置连起来,构成了一个每个点只有一个入边 ...

  3. SQL死锁

    我们操作数据库大量数据时,可能会出现死锁现象. 所谓死锁: 是指两个或两个以上的进程在执行过程中,因争夺资源而造成的一种互相等待的现象,若无外力作用,它们都将无法推进下去.此时称系统处于死锁状态或系统 ...

  4. Vue中slot内容分发

    <slot>元素是一个内容分发API,使用多个内容插槽时可指定name属性 <!DOCTYPE html> <html> <head> <meta ...

  5. StringBuilder与StringBuffer

    转:http://www.cnblogs.com/pepcod/archive/2013/02/16/2913557.html JAVA中用于处理字符串常用的有三个类: java.lang.Strin ...

  6. ubuntu 配置虚拟主机

    ubuntu下Apache虚拟主机的配置   启用站点停用站点方法   a2ensite/a2dissite 比如添加一个ecshop 的虚拟机 首先到/etc/apache2/site-availa ...

  7. Page_Load与Page_PreRender的执行顺序

    原文发布时间为:2009-10-25 -- 来源于本人的百度文章 [由搬家工具导入] Page_PreRender 服务器控件将要呈现给其包含的 控件时发生。简单的理解为page中的控件渲染调用此事件 ...

  8. FusionCharts参数大全

    原文发布时间为:2010-01-11 -- 来源于本人的百度文章 [由搬家工具导入] Fusioncharts 参数 objects ANCHORS 锚点 用于标识line或area的数值点 支持效果 ...

  9. 原生app与js交互 jsSDK设计

    var UA = window.navigator.userAgent.toLowerCase()var isIOS = UA && /iphone|ipad|ipod|ios/.te ...

  10. 插入排序Insertion sort(转)

    插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕.     插入排序方法分直接插入排序和折半插入排序两种,这里只介绍直接插入排序,折半插入排序留到“查找”内 ...