Added missing body pattern comparison

without this change the eact contents of the body were mostly ignored
with this change we support all WireMock body matching patterns

fixes #135
This commit is contained in:
Marcin Grzejszczak
2016-12-29 15:38:34 +01:00
parent a57ac0a5ea
commit 4ceaff5b66
8 changed files with 297 additions and 9 deletions

View File

@@ -23,18 +23,24 @@ import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import javax.xml.xpath.XPathExpressionException;
import org.hamcrest.BaseMatcher;
import org.hamcrest.Description;
import org.hamcrest.MatcherAssert;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.client.ClientHttpRequest;
import org.springframework.mock.http.client.MockClientHttpRequest;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.test.web.client.MockRestServiceServer.MockRestServiceServerBuilder;
import org.springframework.test.web.client.RequestMatcher;
import org.springframework.test.web.client.ResponseActions;
import org.springframework.test.web.client.match.MockRestRequestMatchers;
import org.springframework.test.web.client.response.DefaultResponseCreator;
import org.springframework.util.StreamUtils;
import org.springframework.util.StringUtils;
@@ -44,8 +50,12 @@ 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.MatchResult;
import com.github.tomakehurst.wiremock.matching.MatchesJsonPathPattern;
import com.github.tomakehurst.wiremock.matching.MatchesXPathPattern;
import com.github.tomakehurst.wiremock.matching.MultiValuePattern;
import com.github.tomakehurst.wiremock.matching.RequestPattern;
import com.github.tomakehurst.wiremock.matching.StringValuePattern;
import com.github.tomakehurst.wiremock.stubbing.StubMapping;
import static org.springframework.test.web.client.match.MockRestRequestMatchers.header;
@@ -192,12 +202,47 @@ public class WireMockRestServiceServer {
for (StubMapping mapping : mappings) {
ResponseActions expect = server.expect(requestTo(request(mapping.getRequest())));
expect.andExpect(method(HttpMethod.valueOf(mapping.getRequest().getMethod().getName())));
mapping.getRequest().getBodyPatterns();
bodyPatterns(expect, mapping.getRequest());
requestHeaders(expect, mapping.getRequest());
expect.andRespond(response(mapping.getResponse()));
}
return server;
}
private void bodyPatterns(ResponseActions expect, RequestPattern request) {
if (request.getBodyPatterns() == null) {
return;
}
for (final StringValuePattern pattern : request.getBodyPatterns()) {
if (pattern instanceof MatchesJsonPathPattern) {
expect.andExpect(MockRestRequestMatchers.jsonPath(((MatchesJsonPathPattern) pattern).getMatchesJsonPath()).exists());
} else if (pattern instanceof MatchesXPathPattern) {
expect.andExpect(xpath((MatchesXPathPattern) pattern));
}
expect.andExpect(matchContents(pattern));
}
}
private RequestMatcher matchContents(final StringValuePattern pattern) {
return new RequestMatcher() {
@Override public void match(ClientHttpRequest request)
throws IOException, AssertionError {
MockClientHttpRequest mockRequest = (MockClientHttpRequest) request;;
MatchResult result = pattern.match(mockRequest.getBodyAsString());
MatcherAssert.assertThat("Request as string [" + mockRequest.getBodyAsString() + "]", result.isExactMatch());
}
};
}
private RequestMatcher xpath(MatchesXPathPattern pattern) {
try {
return MockRestRequestMatchers.xpath(pattern.getMatchesXPath()).exists();
} catch (XPathExpressionException e) {
throw new IllegalStateException(e);
}
}
private String request(RequestPattern request) {
return this.baseUrl + (request.getUrlPath() == null ? (request.getUrl() == null ? "/" : request.getUrl())
: request.getUrlPath());

View File

@@ -1,6 +1,8 @@
package org.springframework.cloud.contract.wiremock;
import java.net.URI;
import java.util.Collections;
import java.util.List;
import org.junit.Test;
import org.springframework.http.MediaType;
@@ -9,6 +11,8 @@ import org.springframework.http.ResponseEntity;
import org.springframework.test.web.client.MockRestServiceServer;
import org.springframework.web.client.RestTemplate;
import com.fasterxml.jackson.annotation.JsonCreator;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.fail;
@@ -217,4 +221,183 @@ public class WiremockMockServerApplicationTests {
String.class)).isEqualTo("Hello World");
}
// Issue #135
@Test
public void postWithBodyMatchingJsonPaths() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.baseUrl("http://example.org") //
.stubs("classpath:/mappings/body-matches-jsonpath.json").build();
assertThat(this.restTemplate.postForObject("http://example.org/body",
new Things(Collections.singletonList(new Thing("RequiredThing"))), String.class))
.isEqualTo("Hello Body");
}
@Test
public void postWithRequestThatHasNonMatchingJsonPaths() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.baseUrl("http://example.org") //
.stubs("classpath:/mappings/body-matches-jsonpath.json").build();
String response;
try {
response = this.restTemplate.postForObject("http://example.org/body",
new Things(Collections.singletonList(new Thing("AbsentThing"))), String.class);
} catch (AssertionError e) {
response = null;
}
if (null != response) {
fail("There was a response for a request that shouldn't be matched : " + response);
}
}
@Test
public void postWithBodyMatchingXPath() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.baseUrl("http://example.org") //
.stubs("classpath:/mappings/body-matches-xpath.json").build();
assertThat(this.restTemplate.exchange(
RequestEntity.post(URI.create("http://example.org/body"))
.contentType(MediaType.APPLICATION_XML)
.body("<things><thing><name>RequiredThing</name></thing></things>"),
String.class).getBody()).isEqualTo("Hello Body");
}
@Test
public void postWithRequestThatHasNonMatchingXPaths() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.baseUrl("http://example.org") //
.stubs("classpath:/mappings/body-matches-xpath.json").build();
ResponseEntity<String> response;
try {
response = this.restTemplate.exchange(
RequestEntity.post(URI.create("http://example.org/body"))
.contentType(MediaType.APPLICATION_XML)
.body("<foo/>"),
String.class);
} catch (AssertionError e) {
response = null;
}
if (null != response) {
fail("There was a response for a request that shouldn't be matched : " + response);
}
}
@Test
public void postWithBodyMatchingJson() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.baseUrl("http://example.org") //
.stubs("classpath:/mappings/body-matches-equaltojson.json").build();
assertThat(this.restTemplate.postForObject("http://example.org/body",
new Things(Collections.singletonList(new Thing("RequiredThing"))), String.class))
.isEqualTo("Hello Body");
}
@Test
public void postWithRequestThatHasNonMatchingJson() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.baseUrl("http://example.org") //
.stubs("classpath:/mappings/body-matches-equaltojson.json").build();
String response;
try {
response = this.restTemplate.postForObject("http://example.org/body",
new Things(Collections.singletonList(new Thing("AbsentThing"))), String.class);
} catch (AssertionError e) {
response = null;
}
if (null != response) {
fail("There was a response for a request that shouldn't be matched : " + response);
}
}
@Test
public void postWithBodyMatchingXml() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.baseUrl("http://example.org") //
.stubs("classpath:/mappings/body-matches-equaltoxml.json").build();
assertThat(this.restTemplate.exchange(
RequestEntity.post(URI.create("http://example.org/body"))
.contentType(MediaType.APPLICATION_XML)
.body("<things><thing><name>RequiredThing</name></thing></things>"),
String.class).getBody()).isEqualTo("Hello Body");
}
@Test
public void postWithRequestThatHasNonMatchingXml() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.baseUrl("http://example.org") //
.stubs("classpath:/mappings/body-matches-equaltoxml.json").build();
ResponseEntity<String> response;
try {
response = this.restTemplate.exchange(
RequestEntity.post(URI.create("http://example.org/body"))
.contentType(MediaType.APPLICATION_XML)
.body("<things><thing><name>AbsentThing</name></thing></things>"),
String.class);
} catch (AssertionError e) {
response = null;
}
if (null != response) {
fail("There was a response for a request that shouldn't be matched : " + response);
}
}
@Test
public void postWithBodyMatchingRegex() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.baseUrl("http://example.org") //
.stubs("classpath:/mappings/body-matches-regex.json").build();
assertThat(this.restTemplate.exchange(
RequestEntity.post(URI.create("http://example.org/body"))
.contentType(MediaType.APPLICATION_XML)
.body("<things><thing><name>RequiredThing</name></thing></things>"),
String.class).getBody()).isEqualTo("Hello Body");
}
@Test
public void postWithRequestThatHasNonMatchingRegex() throws Exception {
WireMockRestServiceServer.with(this.restTemplate) //
.baseUrl("http://example.org") //
.stubs("classpath:/mappings/body-matches-regex.json").build();
ResponseEntity<String> response;
try {
response = this.restTemplate.exchange(
RequestEntity.post(URI.create("http://example.org/body"))
.contentType(MediaType.APPLICATION_XML)
.body("<things><thing><name>AbsentThing</name></thing></things>"),
String.class);
} catch (AssertionError e) {
response = null;
}
if (null != response) {
fail("There was a response for a request that shouldn't be matched : " + response);
}
}
public static class Things {
public List<Thing> things;
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public Things(List<Thing> things) {
this.things = things;
}
}
public static class Thing {
public String name;
@JsonCreator(mode = JsonCreator.Mode.PROPERTIES)
public Thing(String name) {
this.name = name;
}
}
}

View File

@@ -0,0 +1,13 @@
{
"request" : {
"urlPath" : "/body",
"method" : "POST",
"bodyPatterns" : [ {
"equalToJson" : "{ \"things\": [ { \"name\" : \"RequiredThing\" } ] }"
} ]
},
"response" : {
"status" : 200,
"body" : "Hello Body"
}
}

View File

@@ -0,0 +1,13 @@
{
"request" : {
"urlPath" : "/body",
"method" : "POST",
"bodyPatterns" : [ {
"equalToXml" : "<things><thing><name>RequiredThing</name></thing></things>"
} ]
},
"response" : {
"status" : 200,
"body" : "Hello Body"
}
}

View File

@@ -0,0 +1,13 @@
{
"request" : {
"urlPath" : "/body",
"method" : "POST",
"bodyPatterns" : [ {
"matchesJsonPath" : "$.things[?(@.name == 'RequiredThing')]"
} ]
},
"response" : {
"status" : 200,
"body" : "Hello Body"
}
}

View File

@@ -0,0 +1,13 @@
{
"request" : {
"urlPath" : "/body",
"method" : "POST",
"bodyPatterns" : [ {
"matches" : ".*RequiredThing.*"
} ]
},
"response" : {
"status" : 200,
"body" : "Hello Body"
}
}

View File

@@ -0,0 +1,13 @@
{
"request" : {
"urlPath" : "/body",
"method" : "POST",
"bodyPatterns" : [ {
"matchesXPath" : "//things"
} ]
},
"response" : {
"status" : 200,
"body" : "Hello Body"
}
}