WireMock和Spring MVC模拟器
Spring Cloud Contract提供了一个方便的类,可以将JSON WireMock存根加载到Spring MockRestServiceServer
中。以下是一个例子:
@RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = WebEnvironment.NONE) public class WiremockForDocsMockServerApplicationTests { @Autowired private RestTemplate restTemplate; @Autowired private Service service; @Test public void contextLoads() throws Exception { // will read stubs classpath MockRestServiceServer server = WireMockRestServiceServer.with(this.restTemplate) .baseUrl("http://example.org").stubs("classpath:/stubs/resource.json") .build(); // We're asserting if WireMock responded properly assertThat(this.service.go()).isEqualTo("Hello World"); server.verify(); } }
baseUrl
前面是所有模拟调用,stubs()
方法将一个存根路径资源模式作为参数。所以在这个例子中,/stubs/resource.json
定义的存根被加载到模拟服务器中,所以如果RestTemplate
被要求访问http://example.org/
,那么它将得到所声明的响应。可以指定多个存根模式,每个可以是一个目录(对于所有“.json”的递归列表)或一个固定的文件名(如上例所示)或一个蚂蚁样式模式。JSON格式是通常的WireMock格式,您可以在WireMock网站上阅读。
目前,我们支持Tomcat,Jetty和Undertow作为Spring Boot嵌入式服务器,而Wiremock本身对特定版本的Jetty(目前为9.2)具有“本机”支持。要使用本地Jetty,您需要添加本机线程依赖关系,并排除Spring Boot容器(如果有的话)。
使用RestDocs生成存根
Spring RestDocs可用于为具有Spring MockMvc或RestEasy的HTTP API生成文档(例如,asciidoctor格式)。在生成API文档的同时,还可以使用Spring Cloud Contract WireMock生成WireMock存根。只需编写正常的RestDocs测试用例,并使用@AutoConfigureRestDocs
在restdocs输出目录中自动存储存根。例如:
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureRestDocs(outputDir = "target/snippets") @AutoConfigureMockMvc public class ApplicationTests { @Autowired private MockMvc mockMvc; @Test public void contextLoads() throws Exception { mockMvc.perform(get("/resource")) .andExpect(content().string("Hello World")) .andDo(document("resource")); } }
从此测试将在“target / snippets / stubs / resource.json”上生成一个WireMock存根。它将所有GET请求与“/ resource”路径相匹配。
没有任何其他配置,这将创建一个存根与HTTP方法的请求匹配器和除“主机”和“内容长度”之外的所有头。为了更准确地匹配请求,例如要匹配POST或PUT的正文,我们需要明确创建一个请求匹配器。这将做两件事情:1)创建一个只匹配您指定的方式的存根,2)断言测试用例中的请求也匹配相同的条件。
主要的入口点是WireMockRestDocs.verify()
,可以替代document()
便利方法。例如:
@RunWith(SpringRunner.class) @SpringBootTest @AutoConfigureRestDocs(outputDir = "target/snippets") @AutoConfigureMockMvc public class ApplicationTests { @Autowired private MockMvc mockMvc; @Test public void contextLoads() throws Exception { mockMvc.perform(post("/resource") .content("{\"id\":\"123456\",\"message\":\"Hello World\"}")) .andExpect(status().isOk()) .andDo(verify().jsonPath("$.id") .stub("resource")); } }
所以这个合同是说:任何有效的POST与“id”字段将得到与本测试相同的响应。您可以将来电链接到.jsonPath()
以添加其他匹配器。如果 您不熟悉JayWay文档,可以帮助您加快JSON路径的速度。
您也可以使用WireMock API来验证请求是否与创建的存根匹配,而不是使用jsonPath
和contentType
方法。例:
@Test public void contextLoads() throws Exception { mockMvc.perform(post("/resource") .content("{\"id\":\"123456\",\"message\":\"Hello World\"}")) .andExpect(status().isOk()) .andDo(verify() .wiremock(WireMock.post( urlPathEquals("/resource")) .withRequestBody(matchingJsonPath("$.id")) .stub("post-resource")); }
WireMock API是丰富的 - 您可以通过正则表达式以及json路径来匹配头文件,查询参数和请求正文,因此这可以用于创建具有更广泛参数的存根。上面的例子会生成一个这样的stub:
{ "request" : { "url" : "/resource", "method" : "POST", "bodyPatterns" : [ { "matchesJsonPath" : "$.id" }] }, "response" : { "status" : 200, "body" : "Hello World", "headers" : { "X-Application-Context" : "application:-1", "Content-Type" : "text/plain" } } }
注意
|
您可以使用wiremock() 方法或jsonPath() 和contentType() 方法创建请求匹配器,但不能同时使用两者。 |
在消费方面,假设上面生成的resource.json
可以在类路径中使用,您可以使用WireMock以多种不同的方式创建一个存根,其中包括上述使用@AutoConfigureWireMock(stubs="classpath:resource.json")
的描述。