diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/DynamicPortPlaceholderInserterPreprocessor.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/DynamicPortPlaceholderInserterPreprocessor.java new file mode 100644 index 0000000000..66e7415172 --- /dev/null +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/DynamicPortPlaceholderInserterPreprocessor.java @@ -0,0 +1,44 @@ +/* + * Copyright 2019-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.wiremock.restdocs; + +import org.springframework.restdocs.operation.OperationRequest; +import org.springframework.restdocs.operation.OperationResponse; +import org.springframework.restdocs.operation.OperationResponseFactory; +import org.springframework.restdocs.operation.preprocess.OperationPreprocessor; + +class DynamicPortPlaceholderInserterPreprocessor implements OperationPreprocessor { + + private final OperationResponseFactory responseFactory = new OperationResponseFactory(); + + @Override + public OperationRequest preprocess(OperationRequest request) { + return request; + } + + @Override + public OperationResponse preprocess(OperationResponse response) { + String content = response.getContentAsString(); + if (content.contains("localhost:8080")) { + content = content.replace("localhost:8080", + "localhost:{{request.requestLine.port}}"); + response = this.responseFactory.createFrom(response, content.getBytes()); + } + return response; + } + +} diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockRestDocsConfiguration.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockRestDocsConfiguration.java index 03841f6f26..bc1f90f121 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockRestDocsConfiguration.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockRestDocsConfiguration.java @@ -21,10 +21,6 @@ import org.springframework.boot.test.autoconfigure.restdocs.RestDocsMockMvcConfi import org.springframework.context.annotation.Configuration; import org.springframework.core.env.Environment; import org.springframework.restdocs.mockmvc.MockMvcRestDocumentationConfigurer; -import org.springframework.restdocs.operation.OperationRequest; -import org.springframework.restdocs.operation.OperationResponse; -import org.springframework.restdocs.operation.OperationResponseFactory; -import org.springframework.restdocs.operation.preprocess.OperationPreprocessor; /** * Custom configuration for Spring RestDocs that adds a WireMock snippet (for generating @@ -53,32 +49,10 @@ public class WireMockRestDocsConfiguration public void customize(MockMvcRestDocumentationConfigurer configurer) { if (this.environment.getProperty("wiremock.placeholders.enabled", "true") .equals("true")) { - configurer.operationPreprocessors() - .withResponseDefaults(new ForwardHeaderPreprocessor()); + configurer.operationPreprocessors().withResponseDefaults( + new DynamicPortPlaceholderInserterPreprocessor()); } configurer.snippets().withAdditionalDefaults(new WireMockSnippet()); } - static class ForwardHeaderPreprocessor implements OperationPreprocessor { - - private final OperationResponseFactory responseFactory = new OperationResponseFactory(); - - @Override - public OperationRequest preprocess(OperationRequest request) { - return request; - } - - @Override - public OperationResponse preprocess(OperationResponse response) { - String content = response.getContentAsString(); - if (content.contains("localhost:8080")) { - content = content.replace("localhost:8080", - "localhost:{{request.requestLine.port}}"); - response = this.responseFactory.createFrom(response, content.getBytes()); - } - return response; - } - - } - } diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockWebTestClientConfiguration.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockWebTestClientConfiguration.java index 1883bcb035..137f16ca1a 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockWebTestClientConfiguration.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/restdocs/WireMockWebTestClientConfiguration.java @@ -19,6 +19,7 @@ package org.springframework.cloud.contract.wiremock.restdocs; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.test.autoconfigure.restdocs.RestDocsWebTestClientConfigurationCustomizer; import org.springframework.context.annotation.Configuration; +import org.springframework.core.env.Environment; import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentationConfigurer; /** @@ -38,8 +39,19 @@ import org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation public class WireMockWebTestClientConfiguration implements RestDocsWebTestClientConfigurationCustomizer { + private final Environment environment; + + public WireMockWebTestClientConfiguration(Environment environment) { + this.environment = environment; + } + @Override public void customize(WebTestClientRestDocumentationConfigurer configurer) { + if (this.environment.getProperty("wiremock.placeholders.enabled", "true") + .equals("true")) { + configurer.operationPreprocessors().withResponseDefaults( + new DynamicPortPlaceholderInserterPreprocessor()); + } configurer.snippets().withAdditionalDefaults(new WireMockSnippet()); } diff --git a/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockServerWebTestClientApplicationTests.java b/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockServerWebTestClientApplicationTests.java index f195b5bb20..5dbe41955c 100644 --- a/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockServerWebTestClientApplicationTests.java +++ b/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockServerWebTestClientApplicationTests.java @@ -16,6 +16,11 @@ package org.springframework.cloud.contract.wiremock; +import java.io.File; +import java.nio.file.Files; + +import com.github.tomakehurst.wiremock.stubbing.StubMapping; +import org.assertj.core.api.BDDAssertions; import org.junit.Test; import org.junit.runner.RunWith; import wiremock.org.eclipse.jetty.http.HttpStatus; @@ -27,12 +32,17 @@ import org.springframework.boot.test.autoconfigure.web.reactive.WebFluxTest; import org.springframework.cloud.contract.wiremock.WiremockServerWebTestClientApplicationTests.TestConfiguration; import org.springframework.context.annotation.Configuration; import org.springframework.http.ResponseEntity; +import org.springframework.http.server.reactive.ServerHttpRequest; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.reactive.server.WebTestClient; import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.util.UriComponents; +import org.springframework.web.util.UriComponentsBuilder; +import static org.hamcrest.CoreMatchers.containsString; import static org.springframework.restdocs.webtestclient.WebTestClientRestDocumentation.document; @RunWith(SpringRunner.class) @@ -58,6 +68,22 @@ public class WiremockServerWebTestClientApplicationTests { .consumeWith(document("status")); } + @Test + public void stubsRenderLinksWithPlaceholder() throws Exception { + this.client.get().uri("/link").exchange().expectBody(String.class) + .value(containsString("link:")).consumeWith(document("link")); + + File file = new File("target/snippets/webtestclient/stubs", "link.json"); + BDDAssertions.then(file).exists(); + StubMapping stubMapping = StubMapping + .buildFrom(new String(Files.readAllBytes(file.toPath()))); + String body = stubMapping.getResponse().getBody(); + BDDAssertions.then(body) + .contains("http://localhost:{{request.requestLine.port}}/link"); + BDDAssertions.then(stubMapping.getResponse().getTransformers()) + .contains("response-template"); + } + @Configuration @RestController protected static class TestConfiguration { @@ -67,6 +93,14 @@ public class WiremockServerWebTestClientApplicationTests { return "Hello World"; } + @ResponseBody + @RequestMapping("/link") + public String link(ServerHttpRequest request) { + UriComponents uriComponents = UriComponentsBuilder.fromHttpRequest(request) + .build(); + return "link: " + uriComponents.toUriString(); + } + @RequestMapping("/status") public ResponseEntity status() { return ResponseEntity.status(HttpStatus.ACCEPTED_202).body("Hello World");