Add support for placeholders for port in restdocs with WebTestClient

See gh-1088
This commit is contained in:
Dave Syer
2019-06-14 15:29:11 +01:00
parent 33c8cbfc87
commit e79e69fb11
4 changed files with 92 additions and 28 deletions

View File

@@ -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;
}
}

View File

@@ -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;
}
}
}

View File

@@ -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());
}

View File

@@ -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<String> status() {
return ResponseEntity.status(HttpStatus.ACCEPTED_202).body("Hello World");