官方文档:http://wiremock.org/docs/
其它资料:https://www.cnblogs.com/tanglang/p/4791198.html
WireMock是一个开源的测试工具,支持HTTP响应存根、请求验证、代理/拦截、记录和回放。最直接的用法:
- 为Web/移动应用构建Mock Service
- 快速创建Web API原型
- 模拟Web Service中错误返回
- 录制HTTP请求和回放
一般开发项目都会把前端组和Service组分开,或者服务间存在依赖的关系,当进度不一致时,可以根据接口构建Mock Service,模拟不同输入/数据/场景,这样不至于影响两组的开发进度。构建Mock Service方法很多,如:开源工具moco、postman、node.js、soapUI。其中soapUI还可以对Service进行功能/性能测试,功能非常齐全,与soapUI相比,Wiremock好在轻便,一个jar包基本能够满足大多数需求,当然,也可以把它引用写进测试代码里。
通过可执行jar文件单独运行:
1、下载可执行jar文件:http://repo1.maven.org/maven2/com/github/tomakehurst/wiremock-standalone/2.13.0/wiremock-standalone-2.13.0.jar
2、通过以下命令运行:
java -jar wiremock-standalone-2.13.0.jar
默认绑定端口是8080
如果我们已经有请求/响应json文件(可以是手动编写也可以是录制生成、修改),可以先把这些文件放在jar文件同一级目录的mappings文件夹中(默认的路径),然后再执行jar文件,当然也可以在执行jar文件时指定到json文件所在的位置
通过命令行参数做更多配置:
--port:设置http端口号,如:--port 9999
--https-port:如果声明该参数,则表示开启HTTPS端口
--root-dir:设置文件根目录,也就是mappings文件夹和__files文件夹所在的位置,其中mappings是请求/响应json文件所在的目录,也是录制生成文件的目录,默认为jar文件所在的当前目录
--record-mappings:设置录制生成文件的目录,默认为jar文件当前目录的mappings文件夹
更多配置请看:http://wiremock.org/docs/running-standalone/
3、启动后,我们便可以访问该HTTP服务器了
例如,端口号为8080,我们手动编写的json文件如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16{ "request" : { "url" : "/userInfo?name=liming&age=23", "method" : "GET" }, "response" : { "status" : 200, "jsonBody" : { "name":"方法方法是是", "age" : "13" }, "headers": { "Content-Type": "application/json ; charset=UTF8" } } }
1)可以通过http://localhost:8080/userInfo?name=liming&age=23来调用模拟的userInfo接口
2)通过http://localhost:8080/__admin/可以看到当前wiremock模拟的所有端口信息
3)jar包自带了json文件的使用手册,访问http://localhost:8080/__admin/docs/可看到如下界面:
点击Swagger_UI可以看到具体每种请求JSON的写法:
我们也可以在官网上查看JSON文件的写法:http://wiremock.org/docs/api/
4、录制/回放
1)打开:http://localhost:8080/__admin/recorder/可看到如下界面:
2)输入目标URL,点击Record按钮进入录制状态。
3)以上面的userInfo接口为例,我们通过浏览器访问http://localhost:8080/userInfo?name=liming&age=23,wiremock收到请求后,然后向目标服务器发起请求http://localhost:9001/userInfo?name=liming&age=23,然后把目标服务器返回的结果返回给我们,同时记下请求和响应的内容。
4)点击stop按钮停止录制,此时可以看到在mappings文件夹中生成一个json文件,记录了之前的请求和响应内容。
5)后续再访问http://localhost:8080/userInfo?name=liming&age=23时,wiremock便会从之前录制的json文件中获取响应信息返回给我们,我们也可以修改json文件从而改变请求响应的内容。
通过引入依赖的方式使用
wiremock源码:https://github.com/spring-cloud/spring-cloud-contract/tree/master
官方例子:https://github.com/spring-cloud/spring-cloud-contract/tree/master/samples/wiremock-tomcat
具体代码请看(码云):https://gitee.com/wudiyong/WireMockEurekaServer.git
1、引入wiremock依赖
1
2
3
4
5
6<dependency> <groupId>com.github.tomakehurst</groupId> <artifactId>wiremock</artifactId> <version>2.12.0</version> </dependency>
或
1
2
3
4
5<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-contract-wiremock</artifactId> </dependency>
2、创建实例并启动
1)如果只是模拟一个普通的HTTP服务端,可以直接在main函数中创建WireMockServer实例并启动:
1
2
3
4
5FileSource filesRoot = new SingleRootFileSource(wireMockFilesRoot+"/"+appName); WireMockServer wireMockServer = new WireMockServer(WireMockConfiguration.options() .bindAddress(wireMockAddress).port(Integer.parseInt(wireMockPort)).fileSource(filesRoot)); wireMockServer.start();
1
2
3
4
5
6
7
8
9@Bean public WireMockServer wireMockServer(){ //创建wiremock对象 FileSource filesRoot = new SingleRootFileSource(wireMockFilesRoot+"/"+appName); WireMockServer wireMockServer = new WireMockServer(WireMockConfiguration.options() .bindAddress(wireMockAddress).port(Integer.parseInt(wireMockPort)).fileSource(filesRoot)); wireMockServer.start(); return wireMockServer; }
wireMockFilesRoot+"/"+appName:mappings文件夹所在的位置
3)如果与JUnit结合使用,可以通过如下方式:
1
2
3@Rule public WireMockRule wireMockRule = new WireMockRule(options().port(8080));
前两种方式和执行jar文件启动方式一样,都可以通过http://localhost:8080/__admin/recorder/来开启/关闭录制
3、特别地,我们需要模拟一个Eureka服务端,我们的服务需要向注册中心注册,所以,选择上面第二种方式使用wiremock
程序中包含两个web服务:
一个是Spring Boot web,用于向注册中心注册,接收请求,然后将请求发到wiremock服务器
另一个是wiremock,用于模拟返回结果
代码如下:
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
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85import java.util.Map; import javax.servlet.http.HttpServletRequest; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.client.RestTemplate; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.github.tomakehurst.wiremock.WireMockServer; @RestController public class MockController { @Autowired RestTemplate restTemplate; @Autowired WireMockServer wireMockServer; @Value("${wireMock.address}") private String wireMockAddress; @Value("${wireMock.port}") private String wireMockPort; private static boolean isProxy = false; @RequestMapping(value = "/**", method = RequestMethod.GET) public Object getAll(HttpServletRequest httpServletRequest ,@RequestParam Map<String, Object> requestMap) { StringBuffer mocoUrl = new StringBuffer(); mocoUrl.append("http://").append(wireMockAddress).append(":") .append(wireMockPort).append(httpServletRequest.getServletPath()); if(!requestMap.isEmpty()){ mocoUrl.append("?"); boolean first = true; for(String key:requestMap.keySet()){ if(!first){ mocoUrl.append("&"); } first = false; mocoUrl.append(key).append("={").append(key).append("}"); } } String jsonStr = restTemplate.getForEntity(mocoUrl.toString(), String.class,requestMap).getBody(); Object object = JSONObject.parse(jsonStr); return object; } @RequestMapping(value = "/**", method = RequestMethod.POST) public Object postAll(HttpServletRequest httpServletRequest ,@RequestBody Object requestBody) { String requestJsonStr = JSON.toJSONString(requestBody); StringBuffer mocoUrl = new StringBuffer(); mocoUrl.append("http://").append(wireMockAddress).append(":") .append(wireMockPort).append(httpServletRequest.getServletPath()); RestTemplate restTemplate = new RestTemplate(); HttpHeaders headers = new HttpHeaders(); MediaType type = MediaType.parseMediaType("application/json; charset=UTF-8"); headers.setContentType(type); // headers.add("Accept", MediaType.APPLICATION_JSON.toString()); HttpEntity<String> formEntity = new HttpEntity<String>(requestJsonStr, headers); String jsonStr = restTemplate.postForEntity(mocoUrl.toString(), formEntity,String.class).getBody(); Object object = JSONObject.parse(jsonStr); return object; } @RequestMapping(value = "/proxyOn" , method = RequestMethod.GET) public String proxyOn(@RequestParam String proxyPath){ if(isProxy){ wireMockServer.stopRecording(); } isProxy = true; //开启录制 wireMockServer.startRecording(proxyPath); return "Proxy is on! The proxyPath is:" + proxyPath; } @RequestMapping(value = "/proxyOff",method = RequestMethod.GET) public String proxyOff(){ if(isProxy){ //关闭录制 wireMockServer.stopRecording(); } isProxy = false; return "Proxy is off!"; } }
录制的步骤如下:
1)启动自己编写的模拟服务器和目标服务器
2)设置被录制的目标服务器地址,然后开启录制,有两种方式:通过wiremock提供的图形界面设置、调用上面代码提供的接口
3)触发客户端发送请求,如果模拟服务器和目标服务器同名,则该请求会按照一定策略分配到不同的服务器,默认是轮询方式,也就是说,触发两次,会有一次请求到达模拟服务器
4)关闭录制,此时看到mappings文件夹下生成了一个新的json文件,至此录制完成,当然可以一起录制多个请求,每次请求对应一个json文件
录制结束后,后续的测试便不需要启动目标服务器了,模拟服务器会根据请求的url和参数返回对应的结果,可以根据需要修改录制结果或手动编写json文件。
最后
以上就是炙热蜜蜂最近收集整理的关于Web服务模拟器——wiremock的全部内容,更多相关Web服务模拟器——wiremock内容请搜索靠谱客的其他文章。
发表评论 取消回复