设为首页 收藏本站
查看: 1140|回复: 0

[经验分享] 玩转单元测试之WireMock

[复制链接]

尚未签到

发表于 2017-3-1 08:41:36 | 显示全部楼层 |阅读模式
玩转单元测试之WireMock -- Web服务模拟器
  WireMock 是一个灵活的库用于 Web 服务测试,和其他测试工具不同的是,WireMock 创建一个实际的 HTTP服务器来运行你的 Web 服务以方便测试。
  它支持 HTTP 响应存根、请求验证、代理/拦截、记录和回放, 并且可以在单元测试下使用或者部署到测试环境。
  它可以用在哪些场景下:


  • 测试移动应用依赖于第三方REST APIs
  • 创建快速原型的APIs
  • 注入否则难于模拟第三方服务中的错误
  • 任何单元测试的代码依赖于web服务的



目录
前提条件
Maven配置
准备工作
Examples
Troubleshooting
参考

前提条件



  • JDK 1.7


  • Maven 3

Maven配置

  pom里添加以下的dependencies



<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>1.53</version>
<classifier>standalone</classifier>
</dependency>
  <dependency>
        <groupId>org.testng</groupId>
        <artifactId>testng</artifactId>
        <version>6.8</version>
  </dependency>
  如果有依赖冲突,可以exclued 掉冲突的依赖, 配置如下


DSC0000.gif DSC0001.gif


<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock</artifactId>
<version>1.53</version>
<!-- Include everything below here if you have dependency conflicts -->
<classifier>standalone</classifier>
<exclusions>
<exclusion>
<groupId>org.mortbay.jetty</groupId>
<artifactId>jetty</artifactId>
</exclusion>
<exclusion>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</exclusion>
<exclusion>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</exclusion>
<exclusion>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</exclusion>
<exclusion>
<groupId>org.skyscreamer</groupId>
<artifactId>jsonassert</artifactId>
</exclusion>
<exclusion>
<groupId>xmlunit</groupId>
<artifactId>xmlunit</artifactId>
</exclusion>
<exclusion>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
</exclusion>
<exclusion>
<groupId>net.sf.jopt-simple</groupId>
<artifactId>jopt-simple</artifactId>
</exclusion>
</exclusions>
</dependency>
exclusions
准备工作

  首先我写了一个类HTTPRequestor用来执行Http request访问Rest服务的, 然后我需要一个Rest服务来测试我写的类是否ok, 但我手上没有一个真实的Rest web service, 所以WireMock就可以出场了,模拟一个Rest web serivce来测试我这个类。
  HTTPRequestor如下:



1 package com.demo.HttpRequestor;
2
3 import static com.jayway.restassured.RestAssured.given;
4
5 import java.util.HashMap;
6 import java.util.Map;
7
8 import org.slf4j.Logger;
9 import org.slf4j.LoggerFactory;
10
11 import com.jayway.restassured.response.Response;
12 import com.jayway.restassured.specification.RequestSpecification;
13
14 /**
15  * Wrapper for RestAssured. Perform an HTTP requests.
16  *
17  * @author wadexu
18  *
19  */
20 public class HTTPRequestor {
21
22         protected static final Logger logger = LoggerFactory.getLogger(HTTPRequestor.class);
23     private RequestSpecification reqSpec;
24     
25
26     /**
27      * Constructor. Initializes the RequestSpecification (relaxedHTTPSValidation
28      * avoids certificate errors).
29      *
30      */
31     public HTTPRequestor() {
32         reqSpec = given().relaxedHTTPSValidation();
33     }
34
35     public HTTPRequestor(String proxy) {
36         reqSpec = given().relaxedHTTPSValidation().proxy(proxy);
37     }
38
39     /**
40      * Performs the request using the stored request data and then returns the response
41      *
42      * @param url
43      * @param method
44      * @param headers
45      * @param body
46      * @return response Response, will contain entire response (response string and status code).
47      * @throws Exception
48      */
49     public Response perform_request(String url, String method, HashMap<String, String> headers, String body) throws Exception {
50         
51         Response response = null;
52         
53         try {
54
55           for(Map.Entry<String, String> entry: headers.entrySet()) {
56             reqSpec.header(entry.getKey(), entry.getValue());
57           }
58      
59           switch(method) {
60      
61             case "GET": {
62               response = reqSpec.get(url);
63               break;
64             }
65             case "POST": {
66               response = reqSpec.body(body).post(url);
67               break;
68             }
69             case "PUT": {
70               response = reqSpec.body(body).put(url);
71               break;
72             }
73             case "DELETE": {
74               response = reqSpec.delete(url);
75               break;
76             }
77      
78             default: {
79               logger.error("Unknown call type: [" + method + "]");
80             }
81           }
82           
83         } catch (Exception e) {
84           logger.error("Problem performing request: ", e);
85         }
86
87         return response;
88       }
89 }
  这个类是需要依赖 jayway 的 rest-assured包的



        <dependency>
<groupId>com.jayway.restassured</groupId>
<artifactId>rest-assured</artifactId>
<version>2.3.3</version>
<scope>test</scope>
</dependency>

Examples

  新建一个测试类HTTPRequestorMockTest
  new 一个 WireMockService 配置一下 然后启动



        wireMockServer = new WireMockServer(wireMockConfig().port(8090));
WireMock.configureFor("localhost", 8090);
wireMockServer.start();
  在测试方法之前
  创建存根, 指明是GET方法,URL路径, Header的内容,会返回什么样的Response



    @BeforeTest
public void stubRequests() {
stubFor(get(urlEqualTo("/cars/Chevy"))
.withHeader("Accept", equalTo("application/json"))
.withHeader("User-Agent", equalTo("Jakarta Commons-HttpClient/3.1"))
.willReturn(aResponse()
.withHeader("content-type", "application/json")
.withStatus(200)
.withBody("{\"message\":\"Chevy car response body\"}")
)
);
}
  ##转载注明出处: http://www.cnblogs.com/wade-xu/p/4299710.html
  一切都模拟好了,接下来开始测试了,测试方法如下



@Test
public void test_Get_Method() {
String url = "http://localhost:8090/cars/Chevy";
String method = "GET";
String body = "";
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Accept", "application/json");
headers.put("User-Agent", "Jakarta Commons-HttpClient/3.1");
HTTPRequestor httpRequestor = new HTTPRequestor();
Response response = null;
try {
response = httpRequestor.perform_request(url, method, headers, body);
} catch (Exception e) {
fail("Problem using HTTPRequestor to generate response: " + e.getMessage());
}
assertEquals(200, response.getStatusCode());
assertEquals("Chevy car response body", response.jsonPath().get("message"));
}
  上面的例子是GET,没有请求体,下面我们来看POST的例子
  同理 创建存根
  RequestBody假设为"Mini Cooper"



stubFor(post(urlEqualTo("/cars/Mini"))
.withHeader("Authorization", equalTo("Basic d8d74jf82o929d"))
.withHeader("Accept", equalTo("application/json"))
.withHeader("User-Agent", equalTo("Jakarta Commons-HttpClient/3.1"))
.withRequestBody(equalTo("Mini Cooper"))
.willReturn(aResponse()
.withHeader("content-type", "application/json")
.withStatus(200)
.withBody("{\"message\":\"Mini Cooper car response body\", \"success\":true}")
)
);
  测试方法如下:



@Test
public void test_Post_Method() {
String url = "http://localhost:8090/cars/Mini";
String method = "POST";
String body = "Mini Cooper";
HashMap<String, String> headers = new HashMap<String, String>();
headers.put("Authorization", "Basic d8d74jf82o929d");
headers.put("Accept", "application/json");
headers.put("User-Agent", "Jakarta Commons-HttpClient/3.1");
HTTPRequestor httpRequestor = new HTTPRequestor();
Response response = null;
try {
response = httpRequestor.perform_request(url, method, headers, body);
} catch (Exception e) {
fail("Problem using HTTPRequestor to generate response: " + e.getMessage());
}
assertEquals(200, response.getStatusCode());
assertEquals("Mini Cooper car response body", response.jsonPath().get("message"));
assertEquals(true, response.jsonPath().get("success"));
}
  PUT 和 DELETE 都是一样的道理,有兴趣的读者可以自行练习。
  测试结束之后 不要忘记tear down, 停掉WireMockServer



@AfterTest(alwaysRun=true)
public void tearDown() {   
wireMockServer.stop();
wireMockServer.shutdown();
}
  贴出我的整个测试类 (两个测试方法都需要同样的参数,所以可以用@DataProvider的方式来改进,我这里就不详细阐述了)





  1 package com.demo.mocktest;
  2
  3 import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
  4 import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
  5 import static com.github.tomakehurst.wiremock.client.WireMock.get;
  6 import static com.github.tomakehurst.wiremock.client.WireMock.post;
  7 import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
  8 import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
  9 import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;
10 import static org.testng.Assert.assertEquals;
11 import static org.testng.Assert.fail;
12
13 import java.util.HashMap;
14
15 import org.testng.ITest;
16 import org.testng.annotations.AfterTest;
17 import org.testng.annotations.BeforeTest;
18 import org.testng.annotations.Test;
19
20 import com.demo.HttpRequestor.HTTPRequestor;
21 import com.github.tomakehurst.wiremock.WireMockServer;
22 import com.github.tomakehurst.wiremock.client.WireMock;
23 import com.jayway.restassured.response.Response;
24
25 public class HTTPRequestorMockTest implements ITest{
26     
27     private WireMockServer wireMockServer;
28     
29     @Override
30     public String getTestName() {
31       return "Mock Test";
32     }
33     
34     public HTTPRequestorMockTest() {
35         wireMockServer = new WireMockServer(wireMockConfig().port(8090));
36         WireMock.configureFor("localhost", 8090);
37         wireMockServer.start();  
38     }
39     
40     @BeforeTest
41     public void stubRequests() {
42       stubFor(get(urlEqualTo("/cars/Chevy"))
43               .withHeader("Accept", equalTo("application/json"))
44               .withHeader("User-Agent", equalTo("Jakarta Commons-HttpClient/3.1"))
45                       .willReturn(aResponse()
46                                   .withHeader("content-type", "application/json")
47                                   .withStatus(200)
48                                   .withBody("{\"message\":\"Chevy car response body\"}")
49                                  )
50              );
51      
52       stubFor(post(urlEqualTo("/cars/Mini"))
53               .withHeader("Authorization", equalTo("Basic d8d74jf82o929d"))
54               .withHeader("Accept", equalTo("application/json"))
55               .withHeader("User-Agent", equalTo("Jakarta Commons-HttpClient/3.1"))
56               .withRequestBody(equalTo("Mini Cooper"))
57                       .willReturn(aResponse()
58                                   .withHeader("content-type", "application/json")
59                                   .withStatus(200)
60                                   .withBody("{\"message\":\"Mini Cooper car response body\", \"success\":true}")
61                                  )
62              );
63     }
64     
65     @Test
66     public void test_Get_Method() {
67         
68         String url = "http://localhost:8090/cars/Chevy";
69         String method = "GET";
70         String body = "";
71         
72         HashMap<String, String> headers = new HashMap<String, String>();
73         headers.put("Accept", "application/json");
74         headers.put("User-Agent", "Jakarta Commons-HttpClient/3.1");
75         
76         
77         HTTPRequestor httpRequestor = new HTTPRequestor();
78         Response response = null;
79         
80         try {
81                 response = httpRequestor.perform_request(url, method, headers, body);
82         } catch (Exception e) {
83                 fail("Problem using HTTPRequestor to generate response: " + e.getMessage());
84         }
85         
86         assertEquals(200, response.getStatusCode());
87         assertEquals("Chevy car response body", response.jsonPath().get("message"));
88         
89     }
90     
91     @Test
92     public void test_Post_Method() {
93         
94         String url = "http://localhost:8090/cars/Mini";
95         String method = "POST";
96         String body = "Mini Cooper";
97         
98         HashMap<String, String> headers = new HashMap<String, String>();
99         headers.put("Authorization", "Basic d8d74jf82o929d");
100         headers.put("Accept", "application/json");
101         headers.put("User-Agent", "Jakarta Commons-HttpClient/3.1");
102         
103         HTTPRequestor httpRequestor = new HTTPRequestor();
104         Response response = null;
105         
106         try {
107                 response = httpRequestor.perform_request(url, method, headers, body);
108         } catch (Exception e) {
109                 fail("Problem using HTTPRequestor to generate response: " + e.getMessage());
110         }
111         
112         assertEquals(200, response.getStatusCode());
113         assertEquals("Mini Cooper car response body", response.jsonPath().get("message"));
114         assertEquals(true, response.jsonPath().get("success"));
115         
116     }
117     
118     @AfterTest(alwaysRun=true)
119     public void tearDown() {   
120       wireMockServer.stop();
121       wireMockServer.shutdown();
122     }
123
124 }
HTTPRequestorMockTest  ##转载注明出处: http://www.cnblogs.com/wade-xu/p/4299710.html
  Run as TestNG
  测试结果如下:



PASSED: Mock Test
PASSED: Mock Test
===============================================
Default test
Tests run: 2, Failures: 0, Skips: 0
===============================================
[TestNG] Time taken by org.testng.reporters.JUnitReportReporter@26b923ee: 7 ms
[TestNG] Time taken by [TestListenerAdapter] Passed:0 Failed:0 Skipped:0]: 1 ms
[TestNG] Time taken by org.testng.reporters.EmailableReporter@512f0124: 5 ms
[TestNG] Time taken by org.testng.reporters.XMLReporter@5a4ec51c: 7 ms
[TestNG] Time taken by org.testng.reporters.SuiteHTMLReporter@5706937e: 31 ms
DSC0002.jpg


Troubleshooting

  HTTPRequestor类第59行 报错Cannot switch on a value of type String for source level below 1.7. Only convertible int values or enum constants are permitted
  --- Java Build Path 设置 JRE System library 1.7 以上
  Static import 如下:



import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.post;
import static com.github.tomakehurst.wiremock.client.WireMock.stubFor;
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.wireMockConfig;

参考

  官方文档:http://wiremock.org/
  感谢阅读,如果您觉得本文的内容对您的学习有所帮助,您可以点击右下方的推荐按钮,您的鼓励是我创作的动力。
  ##转载注明出处: http://www.cnblogs.com/wade-xu/p/4299710.html

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-348563-1-1.html 上篇帖子: Webx框架自带的petstore 下篇帖子: 跟我一起数据挖掘(22)——spark入门
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表