Web服务模拟器——wiremock

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/wudiyong22/article/details/78922238

官方文档: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文件如下:

{
  "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. <dependency>
  2. <groupId>com.github.tomakehurst </groupId>
  3. <artifactId>wiremock </artifactId>
  4. <version>2.12.0 </version>
  5. </dependency>


 
 
  1. <dependency>
  2. <groupId>org.springframework.cloud </groupId>
  3. <artifactId>spring-cloud-contract-wiremock </artifactId>
  4. </dependency>


2、创建实例并启动

1)如果只是模拟一个普通的HTTP服务端,可以直接在main函数中创建WireMockServer实例并启动:


 
 
  1. FileSource filesRoot = new SingleRootFileSource(wireMockFilesRoot+ "/"+appName);
  2. WireMockServer wireMockServer = new WireMockServer(WireMockConfiguration.options()
  3. .bindAddress(wireMockAddress).port(Integer.parseInt(wireMockPort)).fileSource(filesRoot));
  4. wireMockServer.start();
2)如果在Spring Boot环境中使用,可以通过以下方式:


 
 
  1. @Bean
  2. public WireMockServer wireMockServer(){
  3. //创建wiremock对象
  4. FileSource filesRoot = new SingleRootFileSource(wireMockFilesRoot+ "/"+appName);
  5. WireMockServer wireMockServer = new WireMockServer(WireMockConfiguration.options()
  6. .bindAddress(wireMockAddress).port(Integer.parseInt(wireMockPort)).fileSource(filesRoot));
  7. wireMockServer.start();
  8. return wireMockServer;
  9. }

wireMockFilesRoot+"/"+appName:mappings文件夹所在的位置

3)如果与JUnit结合使用,可以通过如下方式:


 
 
  1. @Rule
  2. public WireMockRule wireMockRule = new WireMockRule(options().port( 8080));

前两种方式和执行jar文件启动方式一样,都可以通过http://localhost:8080/__admin/recorder/来开启/关闭录制

3、特别地,我们需要模拟一个Eureka服务端,我们的服务需要向注册中心注册,所以,选择上面第二种方式使用wiremock

程序中包含两个web服务:

一个是Spring Boot web,用于向注册中心注册,接收请求,然后将请求发到wiremock服务器

另一个是wiremock,用于模拟返回结果

代码如下:


 
 
  1. import java.util.Map;
  2. import javax.servlet.http.HttpServletRequest;
  3. import org.springframework.beans.factory.annotation.Autowired;
  4. import org.springframework.beans.factory.annotation.Value;
  5. import org.springframework.http.HttpEntity;
  6. import org.springframework.http.HttpHeaders;
  7. import org.springframework.http.MediaType;
  8. import org.springframework.web.bind.annotation.RequestBody;
  9. import org.springframework.web.bind.annotation.RequestMapping;
  10. import org.springframework.web.bind.annotation.RequestMethod;
  11. import org.springframework.web.bind.annotation.RequestParam;
  12. import org.springframework.web.bind.annotation.RestController;
  13. import org.springframework.web.client.RestTemplate;
  14. import com.alibaba.fastjson.JSON;
  15. import com.alibaba.fastjson.JSONObject;
  16. import com.github.tomakehurst.wiremock.WireMockServer;
  17. @RestController
  18. public class MockController {
  19. @Autowired
  20. RestTemplate restTemplate;
  21. @Autowired
  22. WireMockServer wireMockServer;
  23. @Value( "${wireMock.address}")
  24. private String wireMockAddress;
  25. @Value( "${wireMock.port}")
  26. private String wireMockPort;
  27. private static boolean isProxy = false;
  28. @RequestMapping(value = "/**", method = RequestMethod.GET)
  29. public Object getAll(HttpServletRequest httpServletRequest ,@RequestParam Map<String, Object> requestMap) {
  30. StringBuffer mocoUrl = new StringBuffer();
  31. mocoUrl.append( "http://").append(wireMockAddress).append( ":")
  32. .append(wireMockPort).append(httpServletRequest.getServletPath());
  33. if(!requestMap.isEmpty()){
  34. mocoUrl.append( "?");
  35. boolean first = true;
  36. for(String key:requestMap.keySet()){
  37. if(!first){
  38. mocoUrl.append( "&");
  39. }
  40. first = false;
  41. mocoUrl.append(key).append( "={").append(key).append( "}");
  42. }
  43. }
  44. String jsonStr = restTemplate.getForEntity(mocoUrl.toString(), String.class,requestMap).getBody();
  45. Object object = JSONObject.parse(jsonStr);
  46. return object;
  47. }
  48. @RequestMapping(value = "/**", method = RequestMethod.POST)
  49. public Object postAll(HttpServletRequest httpServletRequest ,@RequestBody Object requestBody) {
  50. String requestJsonStr = JSON.toJSONString(requestBody);
  51. StringBuffer mocoUrl = new StringBuffer();
  52. mocoUrl.append( "http://").append(wireMockAddress).append( ":")
  53. .append(wireMockPort).append(httpServletRequest.getServletPath());
  54. RestTemplate restTemplate = new RestTemplate();
  55. HttpHeaders headers = new HttpHeaders();
  56. MediaType type = MediaType.parseMediaType( "application/json; charset=UTF-8");
  57. headers.setContentType(type);
  58. // headers.add("Accept", MediaType.APPLICATION_JSON.toString());
  59. HttpEntity<String> formEntity = new HttpEntity<String>(requestJsonStr, headers);
  60. String jsonStr = restTemplate.postForEntity(mocoUrl.toString(), formEntity,String.class).getBody();
  61. Object object = JSONObject.parse(jsonStr);
  62. return object;
  63. }
  64. @RequestMapping(value = "/proxyOn" , method = RequestMethod.GET)
  65. public String proxyOn(@RequestParam String proxyPath){
  66. if(isProxy){
  67. wireMockServer.stopRecording();
  68. }
  69. isProxy = true;
  70. //开启录制
  71. wireMockServer.startRecording(proxyPath);
  72. return "Proxy is on! The proxyPath is:" + proxyPath;
  73. }
  74. @RequestMapping(value = "/proxyOff",method = RequestMethod.GET)
  75. public String proxyOff(){
  76. if(isProxy){
  77. //关闭录制
  78. wireMockServer.stopRecording();
  79. }
  80. isProxy = false;
  81. return "Proxy is off!";
  82. }
  83. }


录制的步骤如下:

1)启动自己编写的模拟服务器和目标服务器

2)设置被录制的目标服务器地址,然后开启录制,有两种方式:通过wiremock提供的图形界面设置、调用上面代码提供的接口

3)触发客户端发送请求,如果模拟服务器和目标服务器同名,则该请求会按照一定策略分配到不同的服务器,默认是轮询方式,也就是说,触发两次,会有一次请求到达模拟服务器

4)关闭录制,此时看到mappings文件夹下生成了一个新的json文件,至此录制完成,当然可以一起录制多个请求,每次请求对应一个json文件

录制结束后,后续的测试便不需要启动目标服务器了,模拟服务器会根据请求的url和参数返回对应的结果,可以根据需要修改录制结果或手动编写json文件。






















  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值