SpringCloud 引用响应中的请求
2023-12-12 18:17 更新
最好的情况是提供固定值,但是有时您需要在响应中引用一个请求。
如果您使用Groovy DSL编写合同,则可以使用fromRequest()
方法,该方法使您可以从HTTP请求中引用一堆元素。您可以使用以下选项:
fromRequest().url()
:返回请求URL和查询参数。fromRequest().query(String key)
:返回具有给定名称的第一个查询参数。fromRequest().query(String key, int index)
:返回具有给定名称的第n个查询参数。fromRequest().path()
:返回完整路径。fromRequest().path(int index)
:返回第n个路径元素。fromRequest().header(String key)
:返回具有给定名称的第一个标头。fromRequest().header(String key, int index)
:返回具有给定名称的第n个标题。fromRequest().body()
:返回完整的请求正文。fromRequest().body(String jsonPath)
:从请求中返回与JSON路径匹配的元素。
如果您使用的是YAML合同定义,则必须使用带有自定义Spring Cloud Contract函数的
Handlebars {{{ }}}
符号来实现此目的。
{{{ request.url }}}
:返回请求URL和查询参数。{{{ request.query.key.[index] }}}
:返回具有给定名称的第n个查询参数。例如,键foo
的第一个条目{{{ request.query.foo.[0] }}}
{{{ request.path }}}
:返回完整路径。{{{ request.path.[index] }}}
:返回第n个路径元素。例如,首次输入`
{{{request.path。[0] }}}{{{ request.headers.key }}}
:返回具有给定名称的第一个标头。{{{ request.headers.key.[index] }}}
:返回具有给定名称的第n个标头。{{{ request.body }}}
:返回完整的请求正文。{{{ jsonpath this 'your.json.path' }}}
:从请求中返回与JSON路径匹配的元素。例如json路径$.foo
-{{{ jsonpath this '$.foo' }}}
考虑以下合同:
YAML。
request: method: GET url: /api/v1/xxxx queryParameters: foo: - bar - bar2 headers: Authorization: - secret - secret2 body: foo: bar baz: 5 response: status: 200 headers: Authorization: "foo {{{ request.headers.Authorization.0 }}} bar" body: url: "{{{ request.url }}}" path: "{{{ request.path }}}" pathIndex: "{{{ request.path.1 }}}" param: "{{{ request.query.foo }}}" paramIndex: "{{{ request.query.foo.1 }}}" authorization: "{{{ request.headers.Authorization.0 }}}" authorization2: "{{{ request.headers.Authorization.1 }}" fullBody: "{{{ request.body }}}" responseFoo: "{{{ jsonpath this '$.foo' }}}" responseBaz: "{{{ jsonpath this '$.baz' }}}" responseBaz2: "Bla bla {{{ jsonpath this '$.foo' }}} bla bla"
运行JUnit测试生成将导致类似于以下示例的测试:
// given: MockMvcRequestSpecification request = given() .header("Authorization", "secret") .header("Authorization", "secret2") .body("{\"foo\":\"bar\",\"baz\":5}"); // when: ResponseOptions response = given().spec(request) .queryParam("foo","bar") .queryParam("foo","bar2") .get("/api/v1/xxxx"); // then: assertThat(response.statusCode()).isEqualTo(200); assertThat(response.header("Authorization")).isEqualTo("foo secret bar"); // and: DocumentContext parsedJson = JsonPath.parse(response.getBody().asString()); assertThatJson(parsedJson).field("['fullBody']").isEqualTo("{\"foo\":\"bar\",\"baz\":5}"); assertThatJson(parsedJson).field("['authorization']").isEqualTo("secret"); assertThatJson(parsedJson).field("['authorization2']").isEqualTo("secret2"); assertThatJson(parsedJson).field("['path']").isEqualTo("/api/v1/xxxx"); assertThatJson(parsedJson).field("['param']").isEqualTo("bar"); assertThatJson(parsedJson).field("['paramIndex']").isEqualTo("bar2"); assertThatJson(parsedJson).field("['pathIndex']").isEqualTo("v1"); assertThatJson(parsedJson).field("['responseBaz']").isEqualTo(5); assertThatJson(parsedJson).field("['responseFoo']").isEqualTo("bar"); assertThatJson(parsedJson).field("['url']").isEqualTo("/api/v1/xxxx?foo=bar&foo=bar2"); assertThatJson(parsedJson).field("['responseBaz2']").isEqualTo("Bla bla bar bla bla");
如您所见,响应中已正确引用了请求中的元素。
生成的WireMock存根应类似于以下示例:
{ "request" : { "urlPath" : "/api/v1/xxxx", "method" : "POST", "headers" : { "Authorization" : { "equalTo" : "secret2" } }, "queryParameters" : { "foo" : { "equalTo" : "bar2" } }, "bodyPatterns" : [ { "matchesJsonPath" : "$[?(@.['baz'] == 5)]" }, { "matchesJsonPath" : "$[?(@.['foo'] == 'bar')]" } ] }, "response" : { "status" : 200, "body" : "{\"authorization\":\"{{{request.headers.Authorization.[0]}}}\",\"path\":\"{{{request.path}}}\",\"responseBaz\":{{{jsonpath this '$.baz'}}} ,\"param\":\"{{{request.query.foo.[0]}}}\",\"pathIndex\":\"{{{request.path.[1]}}}\",\"responseBaz2\":\"Bla bla {{{jsonpath this '$.foo'}}} bla bla\",\"responseFoo\":\"{{{jsonpath this '$.foo'}}}\",\"authorization2\":\"{{{request.headers.Authorization.[1]}}}\",\"fullBody\":\"{{{escapejsonbody}}}\",\"url\":\"{{{request.url}}}\",\"paramIndex\":\"{{{request.query.foo.[1]}}}\"}", "headers" : { "Authorization" : "{{{request.headers.Authorization.[0]}}};foo" }, "transformers" : [ "response-template" ] } }
发送请求(例如合同的request
部分中提出的请求)会导致发送以下响应正文:
{ "url" : "/api/v1/xxxx?foo=bar&foo=bar2", "path" : "/api/v1/xxxx", "pathIndex" : "v1", "param" : "bar", "paramIndex" : "bar2", "authorization" : "secret", "authorization2" : "secret2", "fullBody" : "{\"foo\":\"bar\",\"baz\":5}", "responseFoo" : "bar", "responseBaz" : 5, "responseBaz2" : "Bla bla bar bla bla" }
此功能仅适用于版本大于或等于2.5.1的WireMock。Spring Cloud Contract验证程序使用WireMock的response-template
响应转换器。它使用把手将“ Mustache{{{ }}}
”模板转换为适当的值。此外,它注册了两个帮助程序功能:
escapejsonbody
:以可以嵌入JSON的格式转义请求正文。jsonpath
:对于给定的参数,在请求正文中找到一个对象。
以上内容是否对您有帮助:
更多建议: