diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippet.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippet.java index 3e96587890..14a386d27e 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippet.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippet.java @@ -120,6 +120,14 @@ public class ContractDslSnippet extends TemplatedSnippet { OperationRequest request = operation.getRequest(); model.put("request_method", request.getMethod()); model.put("request_url", prepareRequestUrl(request.getUri())); + String rawQuery = request.getUri().getRawQuery(); + boolean urlPathPresent = StringUtils.hasText(rawQuery); + model.put("request_urlpath_present", urlPathPresent); + if (urlPathPresent) { + // TODO: Add support for multiple values + model.put("request_queryparams", + request.getParameters().toSingleValueMap().entrySet()); + } model.put("request_body_present", request.getContent().length > 0); model.put("request_body", request.getContentAsString()); Map headers = new HashMap<>( @@ -144,12 +152,7 @@ public class ContractDslSnippet extends TemplatedSnippet { } private String prepareRequestUrl(URI uri) { - String path = uri.getRawPath(); - String query = uri.getRawQuery(); - if (StringUtils.hasText(query)) { - path = path + "?" + query; - } - return path; + return uri.getRawPath(); } private Map createModelForContract(Operation operation) { diff --git a/spring-cloud-contract-wiremock/src/main/resources/org/springframework/restdocs/templates/default-dsl-contract-only.snippet b/spring-cloud-contract-wiremock/src/main/resources/org/springframework/restdocs/templates/default-dsl-contract-only.snippet index 4994310dbc..550a438ea6 100644 --- a/spring-cloud-contract-wiremock/src/main/resources/org/springframework/restdocs/templates/default-dsl-contract-only.snippet +++ b/spring-cloud-contract-wiremock/src/main/resources/org/springframework/restdocs/templates/default-dsl-contract-only.snippet @@ -3,7 +3,13 @@ import org.springframework.cloud.contract.spec.Contract Contract.make { request { method '{{request_method}}' - url '{{request_url}}' + urlPath('{{request_url}}') {{#request_urlpath_present}} { + queryParameters { + {{#request_queryparams}} + parameter('''{{key}}''', '''{{value}}''') + {{/request_queryparams}} + } + } {{/request_urlpath_present}} {{#request_body_present}} body('''{{request_body}}''') {{/request_body_present}} diff --git a/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java b/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java index 0f259a86b3..a163041627 100644 --- a/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java +++ b/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java @@ -20,6 +20,7 @@ import java.io.File; import java.net.URISyntaxException; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.junit.Before; @@ -32,6 +33,7 @@ import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.cloud.contract.spec.Contract; import org.springframework.cloud.contract.spec.internal.Header; +import org.springframework.cloud.contract.spec.internal.QueryParameter; import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter; import org.springframework.context.annotation.Configuration; import org.springframework.http.HttpHeaders; @@ -43,6 +45,7 @@ import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.WebApplicationContext; @@ -106,8 +109,8 @@ public class ContractDslSnippetTests { then(headerNames(parsedContract.getResponse().getHeaders().getEntries())) .doesNotContain(HttpHeaders.HOST, HttpHeaders.CONTENT_LENGTH); then(parsedContract.getRequest().getMethod().getClientValue()).isNotNull(); - then(parsedContract.getRequest().getUrl().getClientValue()).isNotNull(); - then(parsedContract.getRequest().getUrl().getClientValue().toString()) + then(parsedContract.getRequest().getUrlPath().getClientValue()).isNotNull(); + then(parsedContract.getRequest().getUrlPath().getClientValue().toString()) .startsWith("/"); then(parsedContract.getRequest().getBody().getClientValue()).isNotNull(); then(parsedContract.getRequest().getBodyMatchers().hasMatchers()).isTrue(); @@ -150,8 +153,8 @@ public class ContractDslSnippetTests { then(headerNames(parsedContract.getResponse().getHeaders().getEntries())) .doesNotContain(HttpHeaders.HOST, HttpHeaders.CONTENT_LENGTH); then(parsedContract.getRequest().getMethod().getClientValue()).isNotNull(); - then(parsedContract.getRequest().getUrl().getClientValue()).isNotNull(); - then(parsedContract.getRequest().getUrl().getClientValue().toString()) + then(parsedContract.getRequest().getUrlPath().getClientValue()).isNotNull(); + then(parsedContract.getRequest().getUrlPath().getClientValue().toString()) .startsWith("/"); then(parsedContract.getRequest().getBody().getClientValue()).isNotNull(); then(parsedContract.getRequest().getBodyMatchers().hasMatchers()).isTrue(); @@ -163,7 +166,9 @@ public class ContractDslSnippetTests { @Test public void should_create_contract_template_and_doc_without_body_and_headers() throws Exception { - this.mockMvc.perform(MockMvcRequestBuilders.get("/foo")) + this.mockMvc + .perform(MockMvcRequestBuilders.get("/foo").param("one", "newValueOne") + .param("two", "newValueTwo")) .andExpect(status().isOk()).andDo(document("empty", dslContract())); then(file("/contracts/empty.groovy")).exists(); @@ -173,9 +178,15 @@ public class ContractDslSnippetTests { Contract parsedContract = parsedContracts.iterator().next(); then(parsedContract.getRequest().getHeaders()).isNull(); then(parsedContract.getRequest().getMethod().getClientValue()).isNotNull(); - then(parsedContract.getRequest().getUrl().getClientValue()).isNotNull(); - then(parsedContract.getRequest().getUrl().getClientValue().toString()) + then(parsedContract.getRequest().getUrlPath().getClientValue()).isNotNull(); + then(parsedContract.getRequest().getUrlPath().getClientValue().toString()) .startsWith("/"); + List parameters = parsedContract.getRequest().getUrlPath() + .getQueryParameters().getParameters(); + QueryParameter one = parameter(parameters, "one"); + QueryParameter two = parameter(parameters, "two"); + then(one.getClientValue()).isEqualTo("newValueOne"); + then(two.getClientValue()).isEqualTo("newValueTwo"); then(parsedContract.getRequest().getBody()).isNull(); then(parsedContract.getResponse().getStatus().getClientValue()).isNotNull(); then(parsedContract.getResponse().getHeaders()).isNull(); @@ -183,6 +194,12 @@ public class ContractDslSnippetTests { then(parsedContract.getResponse().getBodyMatchers()).isNull(); } + private QueryParameter parameter(List parameters, String name) { + return parameters.stream() + .filter(queryParameter -> queryParameter.getName().equals(name)) + .findFirst().orElseThrow(() -> new AssertionError("Missing entry")); + } + private Set headerNames(Set
headers) { Set names = new HashSet<>(); for (Header header : headers) { @@ -206,7 +223,8 @@ public class ContractDslSnippetTests { } @GetMapping("/foo") - void getFoo() { + void getFoo(@RequestParam(name = "one", defaultValue = "valueOne") String one, + @RequestParam(name = "two", defaultValue = "valueTwo") String two) { } }