Skip to content

Commit

Permalink
Merge branch '1.0.x'
Browse files Browse the repository at this point in the history
fixes #135
  • Loading branch information
marcingrzejszczak committed Dec 29, 2016
2 parents cdd0102 + 4ceaff5 commit b7101f2
Show file tree
Hide file tree
Showing 8 changed files with 297 additions and 9 deletions.
13 changes: 4 additions & 9 deletions README.adoc
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
// Do not edit this file (e.g. go instead to src/main/asciidoc)

image::https://badges.gitter.im/Join%20Chat.svg[Gitter, link="https://gitter.im/spring-cloud/spring-cloud-contract?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge"]
image::https://codecov.io/gh/spring-cloud/spring-cloud-contract/branch/master/graph/badge.svg["codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-contract"]
image::https://codecov.io/gh/spring-cloud/spring-cloud-contract/branch/1.0.x/graph/badge.svg["codecov", link="https://codecov.io/gh/spring-cloud/spring-cloud-contract"]
image::https://circleci.com/gh/spring-cloud/spring-cloud-contract.svg?style=svg["CircleCI", link="https://circleci.com/gh/spring-cloud/spring-cloud-contract"]

== Spring Cloud Contract
Expand Down Expand Up @@ -1318,7 +1318,7 @@ Example of a `pom.xml` inside the `server` folder.
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.4.2.BUILD-SNAPSHOT</version>
<version>1.5.0.BUILD-SNAPSHOT</version>
<relativePath />
</parent>
Expand Down Expand Up @@ -1566,25 +1566,20 @@ follow the guidelines below.

=== Sign the Contributor License Agreement
Before we accept a non-trivial patch or pull request we will need you to sign the
https://cla.pivotal.io/sign/spring[Contributor License Agreement].
https://support.springsource.com/spring_committer_signup[contributor's agreement].
Signing the contributor's agreement does not grant anyone commit rights to the main
repository, but it does mean that we can accept your contributions, and you will get an
author credit if we do. Active contributors might be asked to join the core team, and
given the ability to merge pull requests.

=== Code of Conduct
This project adheres to the Contributor Covenant https://github.com/spring-cloud/spring-cloud-build/blob/master/docs/src/main/asciidoc/code-of-conduct.adoc[code of
conduct]. By participating, you are expected to uphold this code. Please report
unacceptable behavior to spring-code-of-conduct@pivotal.io.

=== Code Conventions and Housekeeping
None of these is essential for a pull request, but they will all help. They can also be
added after the original pull request but before a merge.

* Use the Spring Framework code format conventions. If you use Eclipse
you can import formatter settings using the
`eclipse-code-formatter.xml` file from the
https://raw.githubusercontent.com/spring-cloud/spring-cloud-build/master/spring-cloud-dependencies-parent/eclipse-code-formatter.xml[Spring
https://github.com/spring-cloud/build/tree/master/eclipse-coding-conventions.xml[Spring
Cloud Build] project. If using IntelliJ, you can use the
http://plugins.jetbrains.com/plugin/6546[Eclipse Code Formatter
Plugin] to import the same file.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,24 @@
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;
Expand All @@ -44,8 +50,12 @@
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;
Expand Down Expand Up @@ -192,12 +202,47 @@ public MockRestServiceServer build() {
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());
Expand Down
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -9,6 +11,8 @@
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;

Expand Down Expand Up @@ -217,4 +221,183 @@ public void simpleGetWithAllStubsInDirectoryWithPeriod() throws Exception {
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;
}
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"request" : {
"urlPath" : "/body",
"method" : "POST",
"bodyPatterns" : [ {
"equalToJson" : "{ \"things\": [ { \"name\" : \"RequiredThing\" } ] }"
} ]
},
"response" : {
"status" : 200,
"body" : "Hello Body"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"request" : {
"urlPath" : "/body",
"method" : "POST",
"bodyPatterns" : [ {
"equalToXml" : "<things><thing><name>RequiredThing</name></thing></things>"
} ]
},
"response" : {
"status" : 200,
"body" : "Hello Body"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"request" : {
"urlPath" : "/body",
"method" : "POST",
"bodyPatterns" : [ {
"matchesJsonPath" : "$.things[?(@.name == 'RequiredThing')]"
} ]
},
"response" : {
"status" : 200,
"body" : "Hello Body"
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"request" : {
"urlPath" : "/body",
"method" : "POST",
"bodyPatterns" : [ {
"matches" : ".*RequiredThing.*"
} ]
},
"response" : {
"status" : 200,
"body" : "Hello Body"
}
}
Loading

0 comments on commit b7101f2

Please sign in to comment.