codecamp

Spring Cloud 使用REST文档生成存根

Spring REST Docs可用于为具有Spring MockMvc或WebTestClient或Rest Assured的HTTP API生成文档(例如,Asciidoctor格式)。在为API生成文档的同时,还可以使用Spring Cloud Contract WireMock生成WireMock存根。为此,编写您的常规REST Docs测试用例,并使用@AutoConfigureRestDocs在REST Docs输出目录中自动生成存根。以下代码显示了使用MockMvc的示例:

@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”路径匹配。WebTestClient相同的示例(用于测试Spring WebFlux应用程序)看起来像这样:

@RunWith(SpringRunner.class)
@SpringBootTest
@AutoConfigureRestDocs(outputDir = "target/snippets")
@AutoConfigureWebTestClient
public class ApplicationTests {

	@Autowired
	private WebTestClient client;

	@Test
	public void contextLoads() throws Exception {
		client.get().uri("/resource").exchange()
				.expectBody(String.class).isEqualTo("Hello World")
 				.consumeWith(document("resource"));
	}
}

在没有任何其他配置的情况下,这些测试将为HTTP方法创建一个带有请求匹配器的存根,以及除“主机”和“内容长度”之外的所有标头。为了更精确地匹配请求(例如,匹配POST或PUT的正文),我们需要显式创建一个请求匹配器。这样做有两个效果:

  • 创建仅以您指定的方式匹配的存根。
  • 断言测试用例中的请求也匹配相同的条件。

此功能的主要入口点是WireMockRestDocs.verify(),它可以代替document()便捷方法,如以下示例所示:

import static org.springframework.cloud.contract.wiremock.restdocs.WireMockRestDocs.verify;
@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"))
                .andDo(document("resource"));
	}
}

该合同规定,任何带有“ id”字段的有效POST都会收到此测试中定义的响应。您可以将对.jsonPath()的呼叫链接在一起以添加其他匹配器。如果不熟悉JSON Path,JayWay文档可以帮助您快速入门此测试的WebTestClient版本具有您插入相同位置的类似的verify()静态助手。

除了jsonPathcontentType便捷方法之外,您还可以使用WireMock API来验证请求是否与创建的存根匹配,如以下示例所示:

@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")))
                       .andDo(document("post-resource"));
}

WireMock API丰富。您可以通过正则表达式以及JSON路径匹配标头,查询参数和请求正文。这些功能可用于创建具有更广泛参数范围的存根。上面的示例生成一个类似于以下示例的存根:

post-resource.json。 

{
  "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在类路径上可用(例如,通过<< publishing-stubs-as-jars)。之后,可以使用WireMock以多种不同方式创建存根,包括使用@AutoConfigureWireMock(stubs="classpath:resource.json"),如本文档前面所述。


Spring Cloud 自定义WireMock配置
Spring Cloud 通过使用REST文档生成Contracts
温馨提示
下载编程狮App,免费阅读超1000+编程语言教程
取消
确定
目录

三、Spring Cloud Netflix

SpringCloud Hystrix超时和Ribbon客户

SpringCloud 重试失败的请求

五、Spring Cloud Stream

六、SpringCloud Binder实现

SpringCloud 重试RabbitMQ Binder

SpringCloud Dead-Letter队列处理

八、Spring Cloud Sleuth

SpringCloud 当前Span

十二、Spring Cloud for Cloud Foundry

十三、Spring Cloud Contract

Spring Cloud Contract验证程序设置

SrpingCloud Gradle项目

十五、Spring Cloud网关

Spring Cloud 配置路由谓词工厂和网关过滤工厂

Spring Cloud TLS / SSL

Spring Cloud网关配置

SpringCloud 故障排除

十八、Spring Cloud GCP

Spring Cloud GCP Spring资源

Spring Cloud Spring JDBC

Spring Cloud Redis的Cloud Memorystore

Spring Cloud 云身份识别代理(IAP)身份验证

关闭

MIP.setData({ 'pageTheme' : getCookie('pageTheme') || {'day':true, 'night':false}, 'pageFontSize' : getCookie('pageFontSize') || 20 }); MIP.watch('pageTheme', function(newValue){ setCookie('pageTheme', JSON.stringify(newValue)) }); MIP.watch('pageFontSize', function(newValue){ setCookie('pageFontSize', newValue) }); function setCookie(name, value){ var days = 1; var exp = new Date(); exp.setTime(exp.getTime() + days*24*60*60*1000); document.cookie = name + '=' + value + ';expires=' + exp.toUTCString(); } function getCookie(name){ var reg = new RegExp('(^| )' + name + '=([^;]*)(;|$)'); return document.cookie.match(reg) ? JSON.parse(document.cookie.match(reg)[2]) : null; }