Fix order of matchers in mock server

It turns out the WireMock does not (I think) contain a comparator
that helps. We have made a custom comparator that helps a bit
(it orders requests with the same URL in reverse order of the
number of headers matched).
This commit is contained in:
Dave Syer
2016-10-11 15:45:27 +02:00
parent 67e75fd2c6
commit 1a88cbd40a
3 changed files with 89 additions and 15 deletions

View File

@@ -35,6 +35,8 @@ import java.io.IOException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import com.github.tomakehurst.wiremock.common.Json;
@@ -43,7 +45,6 @@ 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;
@@ -151,7 +152,7 @@ public class WireMockRestServiceServer {
*/
public MockRestServiceServer build() {
MockRestServiceServer server = this.builder.build();
SortedConcurrentMappingSet mappings = new SortedConcurrentMappingSet();
List<StubMapping> mappings = new ArrayList<>();
for (String location : this.locations) {
try {
for (Resource resource : this.resolver.getResources(pattern(location))) {
@@ -164,6 +165,7 @@ public class WireMockRestServiceServer {
e);
}
}
Collections.sort(mappings, new StubMappingComparator());
for (StubMapping mapping : mappings) {
ResponseActions expect = server
.expect(requestTo(request(mapping.getRequest())));
@@ -247,4 +249,42 @@ public class WireMockRestServiceServer {
return value == null ? MediaType.TEXT_PLAIN : MediaType.valueOf(value);
}
private static class StubMappingComparator implements Comparator<StubMapping> {
@Override
public int compare(StubMapping one, StubMapping two) {
if (one==two) {
return 0;
}
int value = request(one.getRequest()).compareTo(request(two.getRequest()));
if (value == 0) {
// Every mapping has a url pattern, and zero or more header patterns
int twos = 0;
if (two.getRequest().getHeaders() != null) {
twos = two.getRequest().getHeaders().size();
}
int ones = 0;
if (one.getRequest().getHeaders() != null) {
ones = one.getRequest().getHeaders().size();
}
value = twos - ones;
if (value == 0) {
// Same number of header matchers
if (two.getPriority() != null) {
return one.getPriority() != null
? one.getPriority() - two.getPriority() : 1;
}
value = (int) (one.getInsertionIndex() - two.getInsertionIndex());
}
}
return value;
}
private String request(RequestPattern request) {
return (request.getUrlPath() == null ? (request.getUrl() == null ? "/" : request.getUrl()) : request.getUrlPath());
}
}
}

View File

@@ -68,33 +68,56 @@ public class WiremockMockServerApplicationTests {
public void postWithHeader() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.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");
.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");
.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();
.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 postWithMoreExactHeaderMatch() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.baseUrl("http://example.org") // order matters...
.stubs("classpath:/mappings/header-matches.json",
"classpath:/mappings/header-matches-precise.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");
.accept(MediaType.valueOf("application/v.bar"))
.header("X-Precise", "true").build(), String.class)
.getBody()).isEqualTo("Precise World");
}
@Test

View File

@@ -0,0 +1,11 @@
{
"request" : {
"urlPath" : "/poster",
"method" : "POST",
"headers" : { "Accept" : { "matches" : ".*/v.bar" }, "X-Precise" : { "equalTo" : "true" }}
},
"response" : {
"status" : 200,
"body" : "Precise World"
}
}