mock测试_mock server3
Mock一个Server
一、Mocker Server位置和作用

二、常见的Mock Server
- WireMock,支持HTTP协议,参考:http://wiremock.org/
- SoapUI MockService 支持 WebService,参考:https://www.soapui.org/
- Dubbo,需要自己实现
- 使用Web框架自己开发Mock Server系统,参考:http://www.testclass.net/interface/flask_mock/
- 在线 Mock Server 系统,参考:http://easy-mock.com/login
- 使用现成的 Mock Server 库创建系统,参考:
MockServer:https://github.com/jamesdbloom/mockserver
Moco:https://github.com/dreamhead/moco
两个项目都不错,有Mock Server库,GitHub上面的 Star 也差不多。
三、Mock Server Moco
1. 简介
简单来说 Moco 就是类似一个 Mock 的工具框架,一个简单搭建模拟服务器的程序库 / 工具,下载就是一个JAR包。
集成,特别是基于 HTTP 协议的集成,例如 web 服务、REST 等,在我们的大多数开发中都被广泛使用。在过去,我们只是将另一场 WAR 包部署到应用服务器上,例如 Jetty 或Tomcat 等。众所周知,开发一个 WAR 包并将其部署到任何应用服务器上是非常枯燥的,即使我们使用的是嵌入式服务器。WAR包也需要被重新打包即使我们只是想稍微改变一下。
简单来说,Moco 就是解决了开发前端时没有后端支持,开发接口时依赖没有到位的尴尬场景。当然 Moco 的灵活性,让其有越来越多的应用场景,比如我们在开发接口测试的时候。
2. 特点:
- 只需要简单的配置 request、response 等即可满足要求,支持 http、https、socket 。可以说是非常的灵活性。
- 支持在 request 中设置 Headers , Cookies , StatusCode 等。
- 对 GET、POST、PUT、DELETE 等请求方式均支持,很适合 web 开发。
- 无需环境配置,有 Java 环境即可。
- 修改配置后,立刻生效。只需要维护接口,也就是契约即可。
- 对可能用到的数据格式都支持,如 Json、text、xml、file 等。
- 还能与其他工具集成,如 Junit、Maven、Gradle 等。
3. 原理
Moco 本身支持 API 和独立运行两种方式。通过 API ,开发人员可以在Junit、TestNg 等测试框架里使用 Moco,这样极大地降低了接口测试的复杂度。Moco 根据一些配置,启动一个真正的 HTTP 服务(监听本地指定端口)。当发起的请求满足一个条件时,就会收到一个 response 。Moco 底层并没有依赖于像 Servlet 这样的重型框架,而是基于 Netty 的网络应用框架编写的,这样就绕过了复杂的应用服务器,所以它的速度是极快的。
4. 加载配置启动 Moco HTTP Server
java -jar <moco-runner-path> http -p <port> -c <configfile-path>
java -jar moco-runner-0.11.0-standalone.jar http -p 12306 -c ./src/main/resources/startupURI.json
启动命令参数含义:
-
- moco-runner-path :
moco-runner-0.11.0-standalone.jar包路径,https://github.com/dreamhead/moco/tree/v0.11.0?tab=readme-ov-file 下载jar包 - port :HTTP 服务监听端口
- configfile-path :配置文件路径
- moco-runner-path :
5. 使用
下面介绍不同的 HTTP 服务,以及如何设置 JSON 文件的参数。
在本地启动一个 http 服务器,其中监听端口是 12306,配置文件是 JSON 文件。只需要本机发起一个request,如:http://localhost:12306。
a. 约定请求 URI
[
{
"description":"这是一个请求URI",
"request":{
"uri":"/7d"
},
"response":{
"text":"success!"
}
}
]
启动命令:
java -jar moco-runner-0.11.0-standalone.jar http -p 12306 -c ./src/main/resources/startupURI.json
通过 Postman 验证服务,测试 Get 请求:

Moco 服务日志 :
09 十二月 2018 11:06:50 [nioEventLoopGroup-3-2] INFO Request received:
GET /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Postman-Token: 7b5a1a47-a287-4674-b94e-c455fc5c645a
X-Lantern-Version: 5.1.0
Content-Length: 0
09 十二月 2018 11:06:50 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
Content-Length: 10
Content-Type: text/plain; charset=utf-8
success!
b. 约定请求 Queries
JSON 脚本
[
{
"description":"这是一个请求queries",
"request":{
"uri":"/7d",
"queries":{
"name":"zuozewei"
}
},
"response":{
"text":"success!"
}
}
]
启动mock http server,通过 Postman 验证服务,测试 Get 请求:

Moco 服务日志:
09 十二月 2018 11:21:04 [nioEventLoopGroup-3-2] INFO Request received:
GET /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Postman-Token: 2d36e386-e022-4478-8acd-258eff4ff684
X-Lantern-Version: 5.1.0
Content-Length: 0
09 十二月 2018 11:21:04 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
Content-Length: 10
Content-Type: text/plain; charset=utf-8
success!
c. 约定请求 Get 方法
JSON脚本:
[
{
"description":"这是一个get请求",
"request":{
"uri":"/7d",
"method":"get"
},
"response":{
"text":"success!"
}
}
]
通过 Postman 验证服务,测试 Get 请求:

Moco 服务日志:
09 十二月 2018 11:26:42 [nioEventLoopGroup-3-2] INFO Request received:
GET /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Postman-Token: ae3250b6-0ec0-4875-8970-d37e5b840820
X-Lantern-Version: 5.1.0
Content-Length: 0
09 十二月 2018 11:26:42 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
Content-Length: 10
Content-Type: text/plain; charset=utf-8
success!
d. 约定请求 Post 方法
JSON 脚本:
[
{
"description":"这是一个post请求",
"request":{
"uri":"/7d",
"method":"post"
},
"response":{
"text":"success!"
}
}
]
通过 Postman 验证服务,测试 Post 请求:

Moco 服务日志:
09 十二月 2018 11:29:30 [nioEventLoopGroup-3-2] INFO Request received:
POST /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Content-Length: 0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Postman-Token: 73f38af1-4efb-473a-b9d2-de0392c65bbe
X-Lantern-Version: 5.1.0
09 十二月 2018 11:29:30 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
Content-Length: 10
Content-Type: text/plain; charset=utf-8
success!
e. 约定请求 Headers
JSON 脚本:
[
{
"description":"这是一个带headers的post请求",
"request":{
"uri":"/7d",
"method":"post",
"headers":{
"content-type":"application/json"
}
},
"response":{
"text":"success!"
}
}
]
通过 Postman 验证服务,测试 Post 请求:
Moco 服务日志:
09 十二月 2018 11:34:43 [nioEventLoopGroup-3-2] INFO Request received:
POST /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Content-Length: 0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: application/json
Postman-Token: 0a82d74b-303f-42a3-9da0-32fd6c604166
X-Lantern-Version: 5.1.0
09 十二月 2018 11:34:43 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
Content-Length: 10
Content-Type: text/plain; charset=utf-8
success!
JSON 脚本:
[
{
"description":"这是一个带cookies的post请求",
"request":{
"uri":"/7d",
"method":"post",
"cookies":{
"login":"7dgroup"
}
},
"response":{
"text":"success!"
}
}
]
通过 Postman 验证服务,测试 Post 请求:

Moco 服务日志:
09 十二月 2018 12:26:46 [nioEventLoopGroup-3-3] INFO Request received:
POST /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Content-Length: 0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Cookie: login=7dgroup
Postman-Token: 36a12412-6eb1-44a4-a2d8-ea222eba8968
X-Lantern-Version: 5.1.0
09 十二月 2018 12:26:46 [nioEventLoopGroup-3-3] INFO Response return:
HTTP/1.1 200
Content-Length: 10
Content-Type: text/plain; charset=utf-8
success!
g. 约定请求 Forms
JSON 脚本:
[
{
"description":"这是一个带forms参数的post请求",
"request":{
"uri":"/7d",
"method":"post",
"forms":{
"name":"zuozewei"
}
},
"response":{
"text":"success!"
}
}
]
通过 Postman 验证服务,测试 Post 请求:
Moco 服务日志:
09 十二月 2018 12:50:47 [nioEventLoopGroup-3-3] INFO Request received:
POST /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Content-Length: 167
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=--------------------------977669308391204172275520
Postman-Token: 308d06bf-c110-4736-9ac4-ee2fe8a4a036
X-Lantern-Version: 5.1.0
<content is binary>
09 十二月 2018 12:50:47 [nioEventLoopGroup-3-3] INFO Response return:
HTTP/1.1 200
Content-Length: 10
Content-Type: text/plain; charset=utf-8
success!
h. 约定请求 URI(Match)
对于 Restful 风格的 url ,支持正则匹配。
JSON 脚本:
[
{
"description":"这是一个请求Match URI",
"request":{
"uri":
{
"match":"/\\w*/7d"
}
},
"response":{
"text":"success!"
}
}
]
通过 Postman 验证服务,测试 Post 请求:
Moco 服务日志:
09 十二月 2018 13:05:48 [nioEventLoopGroup-7-2] INFO Request received:
POST /wzuozewei/7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Content-Length: 0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=--------------------------767805110351846142172059
Postman-Token: 5d7b5c65-1f8b-46ae-8868-62def1a5de31
X-Lantern-Version: 5.1.0
09 十二月 2018 13:05:48 [nioEventLoopGroup-7-2] INFO Response return:
HTTP/1.1 200
Content-Length: 10
Content-Type: text/plain; charset=utf-8
success!
i. 约定请求 URI(StartsWith)
JSON 脚本:
[
{
"description":"这是一个请求StartsWith URI",
"request":{
"uri":
{
"startsWith":"/7d"
}
},
"response":{
"text":"success!"
}
}
]
通过 Postman 验证服务,测试 Get 请求:

Moco 服务日志:
09 十二月 2018 13:12:43 [nioEventLoopGroup-3-2] INFO Request received:
GET /7d/zuozewei HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=--------------------------445269276531904972620891
Postman-Token: f9deca3a-9b59-426c-ad48-00ebb4800321
X-Lantern-Version: 5.1.0
Content-Length: 0
09 十二月 2018 13:12:43 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
Content-Length: 10
Content-Type: text/plain; charset=utf-8
success!
j. 约定请求 URI(endsWith)
JSON 脚本:
[
{
"description":"这是一个请求endsWith URI",
"request":{
"uri":
{
"endsWith":"/7d"
}
},
"response":{
"text":"success!"
}
}
]
通过 Postman 验证服务,测试 Get 请求:
Moco 服务日志:
09 十二月 2018 13:16:48 [nioEventLoopGroup-3-2] INFO Request received:
GET /zuozewei/7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=--------------------------516453569550782372688423
Postman-Token: 774378a6-5e57-4cc2-a015-f4b3bd2cb84d
X-Lantern-Version: 5.1.0
Content-Length: 0
09 十二月 2018 13:16:48 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
Content-Length: 10
Content-Type: text/plain; charset=utf-8
success!
k. 约定请求 URI(Contain)
JSON 脚本:
[
{
"description":"这是一个请求Contain URI",
"request":{
"uri":
{
"contain":"/7d"
}
},
"response":{
"text":"success!"
}
}
]
通过 Postman 验证服务,测试 Get 请求:
Moco 服务日志:
09 十二月 2018 13:20:28 [nioEventLoopGroup-3-2] INFO Request received:
GET /zuozewei/7d/12345 HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=--------------------------030965700716204296542028
Postman-Token: 7615db1b-77e1-40f7-bdc3-e464c4e7269a
X-Lantern-Version: 5.1.0
Content-Length: 0
09 十二月 2018 13:20:28 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
Content-Length: 10
Content-Type: text/plain; charset=utf-8
success!
l. 约定指定 Json 响应
JSON 脚本:
[
{
"description":"这是一个指定Json响应的post请求",
"request":{
"uri":"/7d",
"method":"post"
},
"response":{
"json":{
"name":"success",
"code":"1"
}
}
}
]
通过 Postman 验证服务,测试 Post 请求:
Moco 服务日志:
09 十二月 2018 13:25:19 [nioEventLoopGroup-3-2] INFO Request received:
POST /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Content-Length: 0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=--------------------------703341725381001692596870
Postman-Token: e5686919-85b9-44d0-8a73-61bf804b6377
X-Lantern-Version: 5.1.0
09 十二月 2018 13:25:19 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
Content-Length: 29
Content-Type: application/json; charset=utf-8
{"name":"success","code":"1"}
m. 约定响应 Status
JSON 脚本:
[
{
"description":"这是指定响应status的get请求",
"request":{
"uri":"/7d",
"method":"get"
},
"response":{
"status":200
}
}
]
通过 Postman 验证服务,测试 Get 请求:
Moco 服务日志:
09 十二月 2018 13:29:07 [nioEventLoopGroup-3-2] INFO Request received:
GET /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=--------------------------465777039297587100709267
Postman-Token: 791fa21c-386f-4389-aaa9-ba06d9e53aff
X-Lantern-Version: 5.1.0
Content-Length: 0
09 十二月 2018 13:29:07 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
n. 约定响应 Headers
JSON 脚本:
[
{
"description":"这是一个get请求",
"request":{
"uri":"/7d",
"method":"get"
},
"response":{
"headers":{
"content-type":"application/json"
}
}
}
]
通过 Postman 验证服务,测试 Get 请求:
Moco 服务日志:
09 十二月 2018 13:34:22 [nioEventLoopGroup-3-2] INFO Request received:
GET /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=--------------------------774041889819140984857561
Postman-Token: 0a51f958-0338-4afa-8ff6-af45d61e12a7
X-Lantern-Version: 5.1.0
Content-Length: 0
09 十二月 2018 13:34:22 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
content-type: application/json
o. 约定响应 Cookies
JSON 脚本:
[
{
"description":"这是一个响应Cookies的get请求",
"request":{
"uri":"/7d",
"method":"get"
},
"response":{
"cookies":{
"login":"7dgroup"
}
}
}
]
通过 Postman 验证服务,测试 Get 请求:

Moco 服务日志:
09 十二月 2018 13:39:00 [nioEventLoopGroup-3-2] INFO Request received:
GET /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=--------------------------315176206881627055625168
Postman-Token: f6d1ae6b-c1c2-474a-827c-f02ed3f23482
X-Lantern-Version: 5.1.0
Content-Length: 0
09 十二月 2018 13:39:00 [nioEventLoopGroup-3-2] INFO Response return:
HTTP/1.1 200
Set-Cookie: login=7dgroup; Path=/
p. 约定重定向 RedirectTo
JSON 脚本:
[
{
"description":"这是一个重定向的get请求",
"request":{
"uri":"/7d",
"method":"get"
},
"redirectTo":"https://www.baidu.com"
}
]
通过浏览器验证服务,测试 Get 请求 http://127.0.0.1:12306/7d,请求会自动重定向到 https://www.baidu.com
Moco 服务日志:
09 十二月 2018 13:43:58 [nioEventLoopGroup-4-2] INFO Request received:
GET /7d HTTP/1.1
Host: 127.0.0.1:12306
User-Agent: PostmanRuntime/7.4.0
Accept: */*
Accept-Encoding: gzip, deflate
Cache-Control: no-cache
Content-Type: multipart/form-data; boundary=--------------------------167408129884853494096695
Cookie: login=7dgroup
Postman-Token: f83696d4-37ba-45b6-aff6-6f20982673ac
X-Lantern-Version: 5.1.0
Content-Length: 0
09 十二月 2018 13:43:58 [nioEventLoopGroup-4-2] INFO Response return:
HTTP/1.1 302
Location: http://www.baidu.com
5. 小结
Moco 的使用很简单,配置也很方便,目前更是提供了 http、rest、socket 服务。但是也仅仅是能 stub 接口,模拟出简单的场景。如果接收到请求后需要做一些处理,如需查询数据库、进行运算、或者一些复杂的操作,就无能为力了。所以是否选用 Moco,就取决于测试人员是否只是需要一个简单的模拟 Server
四、 WireMock
1. 简介
WireMock 是一个HTTP模拟服务,其核心也是一个WEB服务,WireMock主要是为特定请求提供固定的返回值。
WireMock可以作为单独进程启动,模拟一个WEB服务器,提供一些API访问,并返回特定的返回值。也可以作为第三方库在项目中使用。
2. WireMock搭建
a. 先下载WireMock的Jar包, 本文使用下载地址如下:https://repo1.maven.org/maven2/com/github/tomakehurst/wiremock-jre8-standalone/2.33.2/wiremock-jre8-standalone-2.33.2.jar
b. 到指定目录启动Jar,同时也可以加一些启动参数。下面的命令表示用9998端口启动这个模拟服务器
java -jar wiremock-jre8-standalone-2.33.2.jar -port 9998
启动界面如下:

3. WireMock使用
WireMock启动时候,会生成 _files 和 mappings 两个文件夹, _files文件夹中可以放一些返回数据文件。mappings文件夹中存放映射关系,使用json格式的文件。

如下图,新建json文件,启动WireMock时会加载这些文件,更新之后只需要重启WireMock即可。

a. 简单API映射
json文件:
{
"mappings": [
{
"request": {
"method": "GET",
"url": "/api/hello"
},
"response": {
"body": "Hello world!",
"headers": {
"Content-Type": "text/plain"
},
"status": 200
}
}
]
}
启动后访问:

b. 返回response中添加header
{
"request": {
"method": "GET",
"url": "/whatever"
},
"response": {
"status": 200,
"headers": {
"Content-Type": "text/plain",
"Set-Cookie": ["session_id=91837492837", "split_test_group=B"],
"Cache-Control": "no-cache"
}
}
}
c. 返回数组
{
"response": {
"status": 200,
"jsonBody": {
"arbitrary_json": [1, 2, 3]
}
}
}
d. 返回指定文件数据 写在_file文件夹里面
json脚本:
{
"request": {
"method": "GET",
"url": "/bodyfile"
},
"response": {
"status": 200,
"bodyFileName": "/myfile.xml"
}
}
_file文件夹下面新建myfile.xml文件:
<items>
<item>buy milk</item>
<item>Ctest</item>
</items>
访问接口则可以直接返回文件中的数据:

e. URL映射
WireMock也支持映射正则表达式:
{
"request": {
"method": "GET",
"urlPattern": "/your/([a-z]*)?and=query"
},
"response":{
"body":"hello",
"status":200
}
}
访问:

f. 指定请求头
{
"request": {
...
"headers": {
"Content-Type": {
"equalTo": "application/json",
"caseInsensitive": true
}
}
...
},
...
}
g. 可变状态请求
requiredScenarioState/newScenarioState 可以记录当前API映射所处的状态以及新的状态,可以通过改变其状态,从而可以使同一个API返回不同的结果。如下面的请求则可以改变状态,返回不同的结果。
{
"mappings": [
{
"scenarioName": "To do list",
"requiredScenarioState": "Started",
"request": {
"method": "GET",
"url": "/todo/items"
},
"response": {
"status": 200,
"body": "< items >< item >Buy milk< /item >< /items >"
}
},
{
"scenarioName": "To do list",
"requiredScenarioState": "Started",
"newScenarioState": "Cancel newspaper item added",
"request": {
"method": "POST",
"url": "/todo/items",
"bodyPatterns": [
{
"contains": "Cancel newspaper subscription"
}
]
},
"response": {
"status": 201
}
},
{
"scenarioName": "To do list",
"requiredScenarioState": "Cancel newspaper item added",
"request": {
"method": "GET",
"url": "/todo/items"
},
"response": {
"status": 200,
"body": "< items >< item >Buy milk< /item >< item >Cancel newspaper subscription< /item >< /items >"
}
}
]
}
第一次访问时,Started状态:

访问第二个post接口,改变其状态;
再次访问API,会返回新的数据:

h. API故障模拟
设置延时返回,如下可以设置定时延迟2秒:
{
"request": {
"method": "GET",
"url": "/delayed"
},
"response": {
"status": 200,
"fixedDelayMilliseconds": 2000
}
}
如下是延迟2秒的返回结果:

同时也可以设置随机的延迟时间:
{
"request": {
"method": "GET",
"url": "/random/delayed"
},
"response": {
"status": 200,
"delayDistribution": {
"type": "lognormal",
"median": 50,
"sigma": 0.4
}
}
}
4. 总结
WireMock可以快速搭建Web服务,可以模拟开发测试需要的各种请求,使用十分方便。对于维护测试环境稳定以及提高开发效率方面都有不错的效果。
浙公网安备 33010602011771号