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 6587602cba..bbb5f36d9a 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,8 @@ package org.springframework.cloud.contract.wiremock; +import org.hamcrest.BaseMatcher; +import org.hamcrest.Description; import org.springframework.core.io.Resource; import org.springframework.core.io.support.PathMatchingResourcePatternResolver; import org.springframework.http.HttpHeaders; @@ -37,9 +39,11 @@ import java.util.List; import com.github.tomakehurst.wiremock.common.Json; import com.github.tomakehurst.wiremock.http.HttpHeader; +import com.github.tomakehurst.wiremock.http.MultiValue; import com.github.tomakehurst.wiremock.http.ResponseDefinition; import com.github.tomakehurst.wiremock.matching.MultiValuePattern; import com.github.tomakehurst.wiremock.matching.RequestPattern; +import com.github.tomakehurst.wiremock.stubbing.SortedConcurrentMappingSet; import com.github.tomakehurst.wiremock.stubbing.StubMapping; import static org.springframework.test.web.client.match.MockRestRequestMatchers.header; @@ -147,14 +151,12 @@ public class WireMockRestServiceServer { */ public MockRestServiceServer build() { MockRestServiceServer server = this.builder.build(); + SortedConcurrentMappingSet mappings = new SortedConcurrentMappingSet(); for (String location : this.locations) { try { for (Resource resource : this.resolver.getResources(pattern(location))) { StubMapping mapping = mapping(resource); - ResponseActions expect = server - .expect(requestTo(request(mapping.getRequest()))); - requestHeaders(expect, mapping.getRequest()); - expect.andRespond(response(mapping.getResponse())); + mappings.add(mapping); } } catch (IOException e) { @@ -162,6 +164,12 @@ public class WireMockRestServiceServer { e); } } + for (StubMapping mapping : mappings) { + ResponseActions expect = server + .expect(requestTo(request(mapping.getRequest()))); + requestHeaders(expect, mapping.getRequest()); + expect.andRespond(response(mapping.getResponse())); + } return server; } @@ -194,10 +202,22 @@ public class WireMockRestServiceServer { if (request.getHeaders() != null) { for (final String header : request.getHeaders().keySet()) { final MultiValuePattern pattern = request.getHeaders().get(header); - // TODO: match the headers - if ("equalTo".equals(pattern.getName())) { - expect.andExpect(header(header, pattern.getExpected())); - } + expect.andExpect(header(header, new BaseMatcher() { + + @Override + public boolean matches(Object item) { + return pattern.match( + new MultiValue(header, Arrays.asList((String) item))) + .isExactMatch(); + } + + @Override + public void describeTo(Description description) { + description + .appendText("should match header: " + header + " with ") + .appendText(pattern.getExpected()); + } + })); } } } 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 40c2f0c625..59f0d0e686 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 @@ -67,14 +67,36 @@ public class WiremockMockServerApplicationTests { @Test public void postWithHeader() throws Exception { WireMockRestServiceServer.with(this.restTemplate) // - .baseUrl("http://example.org") // - .stubs("classpath:/mappings/*.json").ignoreExpectOrder(true).build(); + .baseUrl("http://example.org") // order matters... + .stubs("classpath:/mappings/poster.json", "classpath:/mappings/accept.json").ignoreExpectOrder(true).build(); assertThat(this.restTemplate .exchange(RequestEntity.post(new URI("http://example.org/poster")) .accept(MediaType.TEXT_PLAIN).build(), String.class) .getBody()).isEqualTo("Accepted World"); } + @Test + public void postWithHeaderContains() throws Exception { + WireMockRestServiceServer.with(this.restTemplate) // + .baseUrl("http://example.org") // order matters... + .stubs("classpath:/mappings/poster.json", "classpath:/mappings/header-contains.json").ignoreExpectOrder(true).build(); + assertThat(this.restTemplate + .exchange(RequestEntity.post(new URI("http://example.org/poster")) + .accept(MediaType.valueOf("application/v.foo")).build(), String.class) + .getBody()).isEqualTo("Foo World"); + } + + @Test + public void postWithHeaderMatches() throws Exception { + WireMockRestServiceServer.with(this.restTemplate) // + .baseUrl("http://example.org") // order matters... + .stubs("classpath:/mappings/poster.json", "classpath:/mappings/header-matches.json").ignoreExpectOrder(true).build(); + assertThat(this.restTemplate + .exchange(RequestEntity.post(new URI("http://example.org/poster")) + .accept(MediaType.valueOf("application/v.bar")).build(), String.class) + .getBody()).isEqualTo("Bar World"); + } + @Test public void simpleGetWithAllStubs() throws Exception { WireMockRestServiceServer.with(this.restTemplate) // diff --git a/spring-cloud-contract-wiremock/src/test/resources/mappings/header-contains.json b/spring-cloud-contract-wiremock/src/test/resources/mappings/header-contains.json new file mode 100644 index 0000000000..b862f326bc --- /dev/null +++ b/spring-cloud-contract-wiremock/src/test/resources/mappings/header-contains.json @@ -0,0 +1,11 @@ +{ + "request" : { + "urlPath" : "/poster", + "method" : "POST", + "headers" : { "Accept" : { "contains" : "v.foo" }} + }, + "response" : { + "status" : 200, + "body" : "Foo World" + } +} \ No newline at end of file diff --git a/spring-cloud-contract-wiremock/src/test/resources/mappings/header-matches.json b/spring-cloud-contract-wiremock/src/test/resources/mappings/header-matches.json new file mode 100644 index 0000000000..80b7582139 --- /dev/null +++ b/spring-cloud-contract-wiremock/src/test/resources/mappings/header-matches.json @@ -0,0 +1,11 @@ +{ + "request" : { + "urlPath" : "/poster", + "method" : "POST", + "headers" : { "Accept" : { "matches" : ".*/v.bar" }} + }, + "response" : { + "status" : 200, + "body" : "Bar World" + } +} \ No newline at end of file