From 3d4cb355c2eb54ac19e2d30a39970fc6f013b661 Mon Sep 17 00:00:00 2001 From: Dave Syer Date: Fri, 11 Nov 2016 13:10:27 +0000 Subject: [PATCH] Add support for files in WireMockRestServiceServer --- .../wiremock/WireMockRestServiceServer.java | 95 +++++++++++-------- .../WiremockMockServerApplicationTests.java | 22 +++++ .../src/test/resources/custom/hello.json | 1 + 3 files changed, 81 insertions(+), 37 deletions(-) create mode 100644 spring-cloud-contract-wiremock/src/test/resources/custom/hello.json diff --git a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockRestServiceServer.java b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockRestServiceServer.java index 8d9e2b1493..e4e94fe93a 100644 --- a/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockRestServiceServer.java +++ b/spring-cloud-contract-wiremock/src/main/java/org/springframework/cloud/contract/wiremock/WireMockRestServiceServer.java @@ -16,6 +16,10 @@ package org.springframework.cloud.contract.wiremock; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.header; +import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; +import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; + import java.io.IOException; import java.nio.charset.Charset; import java.util.ArrayList; @@ -26,7 +30,6 @@ import java.util.List; import org.hamcrest.BaseMatcher; import org.hamcrest.Description; -import org.springframework.core.io.ClassPathResource; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.http.HttpHeaders; @@ -48,10 +51,6 @@ import com.github.tomakehurst.wiremock.matching.MultiValuePattern; import com.github.tomakehurst.wiremock.matching.RequestPattern; import com.github.tomakehurst.wiremock.stubbing.StubMapping; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.header; -import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo; -import static org.springframework.test.web.client.response.MockRestResponseCreators.withStatus; - /** * Convenience class for loading WireMock stubs into a {@link MockRestServiceServer}. In * this way using a {@link RestTemplate} can mock the responses from a server using @@ -72,6 +71,8 @@ public class WireMockRestServiceServer { private List locations = new ArrayList(); + private List files = new ArrayList(); + private boolean ignoreExpectOrder = true; private WireMockRestServiceServer(RestTemplate restTemplate) { @@ -90,8 +91,8 @@ public class WireMockRestServiceServer { /** * Flag to tell the MockRestServiceServer to ignore the order of calls when matching - * requests. The default is true because there is an implied ordering in the stubs - * (by url path and with more specific request matchers first). + * requests. The default is true because there is an implied ordering in the stubs (by + * url path and with more specific request matchers first). * * @param ignoreExpectOrder flag value (default true) * @return this @@ -148,6 +149,18 @@ public class WireMockRestServiceServer { return this; } + /** + * Add some resource locations for files that represent response bodies. Wiremock + * defaults to "file:src/test/resources/__files". + * + * @param locations + * @return this + */ + public WireMockRestServiceServer files(String... locations) { + this.files.addAll(Arrays.asList(locations)); + return this; + } + /** * Build a MockRestServiceServer from the configured stubs. The server can later be * verified (optionally), if you need to check that all expected requests were made. @@ -168,16 +181,14 @@ public class WireMockRestServiceServer { } } catch (IOException e) { - throw new IllegalStateException("Cannot load resources for: " + location, - e); + throw new IllegalStateException("Cannot load resources for: " + location, e); } } if (this.ignoreExpectOrder) { Collections.sort(mappings, new StubMappingComparator()); } for (StubMapping mapping : mappings) { - ResponseActions expect = server - .expect(requestTo(request(mapping.getRequest()))); + ResponseActions expect = server.expect(requestTo(request(mapping.getRequest()))); requestHeaders(expect, mapping.getRequest()); expect.andRespond(response(mapping.getResponse())); } @@ -185,8 +196,7 @@ public class WireMockRestServiceServer { } private String request(RequestPattern request) { - return this.baseUrl + (request.getUrlPath() == null - ? (request.getUrl() == null ? "/" : request.getUrl()) + return this.baseUrl + (request.getUrlPath() == null ? (request.getUrl() == null ? "/" : request.getUrl()) : request.getUrlPath()); } @@ -201,29 +211,44 @@ public class WireMockRestServiceServer { } private StubMapping mapping(Resource resource) throws IOException { - return Json.read(StreamUtils.copyToString(resource.getInputStream(), - Charset.defaultCharset()), StubMapping.class); + return Json.read(StreamUtils.copyToString(resource.getInputStream(), Charset.defaultCharset()), + StubMapping.class); } private DefaultResponseCreator response(ResponseDefinition response) { - return withStatus(HttpStatus.valueOf(response.getStatus())) - .body(body(response)).contentType(contentType(response)) - .headers(responseHeaders(response)); + return withStatus(HttpStatus.valueOf(response.getStatus())).body(body(response)) + .contentType(contentType(response)).headers(responseHeaders(response)); } private String body(ResponseDefinition response) { - if (response.getBody()!=null) { + if (response.getBody() != null) { return response.getBody(); } String file = response.getBodyFileName(); - if (file!=null) { - ClassPathResource files = new ClassPathResource("__files/"); - if (files.exists()) { + if (file != null) { + List locations = this.files.isEmpty() ? Arrays.asList("classpath:/__files/") : this.files; + for (String location : locations) { try { - return StreamUtils.copyToString(files.createRelative(file).getInputStream(), Charset.forName("UTF-8")); + if (!location.endsWith("/")) { + location = location + "/"; + } + for (Resource files : resolver.getResources(location)) { + if (files.exists()) { + try { + Resource resource = files.createRelative(file); + if (resource.exists()) { + return StreamUtils.copyToString(resource.getInputStream(), + Charset.forName("UTF-8")); + } + } + catch (IOException e) { + throw new IllegalStateException("Cannot locate body file: " + file, e); + } + } + } } catch (IOException e) { - throw new IllegalStateException("Cannot locate body file: " + file, e); + // Ignore } } } @@ -238,15 +263,12 @@ public class WireMockRestServiceServer { @Override public boolean matches(Object item) { - return pattern.match( - new MultiValue(header, Arrays.asList((String) item))) - .isExactMatch(); + return pattern.match(new MultiValue(header, Arrays.asList((String) item))).isExactMatch(); } @Override public void describeTo(Description description) { - description - .appendText("should match header: " + header + " with ") + description.appendText("should match header: " + header + " with ") .appendText(pattern.getExpected()); } })); @@ -289,14 +311,15 @@ public class WireMockRestServiceServer { int value = request(one.getRequest()).compareTo(request(two.getRequest())); if (value == 0) { - if (one.getPriority()!=null) { - if (two.getPriority()!=null) { + if (one.getPriority() != null) { + if (two.getPriority() != null) { return one.getPriority().compareTo(two.getPriority()); - } else { + } + else { return -one.getPriority(); } } - if (two.getPriority()!=null) { + if (two.getPriority() != null) { return -two.getPriority(); } @@ -313,8 +336,7 @@ public class WireMockRestServiceServer { if (value == 0) { // Same number of header matchers if (two.getPriority() != null) { - return one.getPriority() != null - ? one.getPriority() - two.getPriority() : 1; + return one.getPriority() != null ? one.getPriority() - two.getPriority() : 1; } value = (int) (one.getInsertionIndex() - two.getInsertionIndex()); } @@ -323,8 +345,7 @@ public class WireMockRestServiceServer { } private String request(RequestPattern request) { - return (request.getUrlPath() == null - ? (request.getUrl() == null ? "/" : request.getUrl()) + return (request.getUrlPath() == null ? (request.getUrl() == null ? "/" : request.getUrl()) : request.getUrlPath()); } diff --git a/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockMockServerApplicationTests.java b/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockMockServerApplicationTests.java index 21375ca214..3b3afde485 100644 --- a/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockMockServerApplicationTests.java +++ b/spring-cloud-contract-wiremock/src/test/java/org/springframework/cloud/contract/wiremock/WiremockMockServerApplicationTests.java @@ -34,6 +34,28 @@ public class WiremockMockServerApplicationTests { server.verify(); } + @Test + public void simpleGetWithBodyFileCustomLocation() throws Exception { + MockRestServiceServer server = WireMockRestServiceServer.with(this.restTemplate) // + .baseUrl("http://example.org") // + .stubs("classpath:/mappings/resource-with-body-file.json") + .files("classpath:/custom/").build(); + assertThat(this.restTemplate.getForObject("http://example.org/resource", + String.class)).isEqualTo("{\"message\":\"Hello Custom\"}"); + server.verify(); + } + + @Test + public void simpleGetWithBodyFileCustomLocationDirectory() throws Exception { + MockRestServiceServer server = WireMockRestServiceServer.with(this.restTemplate) // + .baseUrl("http://example.org") // + .stubs("classpath:/mappings/resource-with-body-file.json") + .files("file:src/test/resources/custom").build(); + assertThat(this.restTemplate.getForObject("http://example.org/resource", + String.class)).isEqualTo("{\"message\":\"Hello Custom\"}"); + server.verify(); + } + @Test public void simpleGetWithEmptyPath() throws Exception { MockRestServiceServer server = WireMockRestServiceServer.with(this.restTemplate) // diff --git a/spring-cloud-contract-wiremock/src/test/resources/custom/hello.json b/spring-cloud-contract-wiremock/src/test/resources/custom/hello.json new file mode 100644 index 0000000000..7afddfdf03 --- /dev/null +++ b/spring-cloud-contract-wiremock/src/test/resources/custom/hello.json @@ -0,0 +1 @@ +{"message":"Hello Custom"} \ No newline at end of file