Implement JSON matching with JSON Content-Type (#208)

fixes #116
This commit is contained in:
Patrice Conil
2017-02-01 10:13:24 +01:00
committed by Marcin Grzejszczak
parent ed30fc6aa5
commit 1337bb0dea
2 changed files with 124 additions and 20 deletions

View File

@@ -43,6 +43,7 @@ import com.github.tomakehurst.wiremock.stubbing.StubMapping;
import static com.github.tomakehurst.wiremock.client.WireMock.aResponse;
import static com.github.tomakehurst.wiremock.client.WireMock.delete;
import static com.github.tomakehurst.wiremock.client.WireMock.equalTo;
import static com.github.tomakehurst.wiremock.client.WireMock.equalToJson;
import static com.github.tomakehurst.wiremock.client.WireMock.get;
import static com.github.tomakehurst.wiremock.client.WireMock.matching;
import static com.github.tomakehurst.wiremock.client.WireMock.matchingJsonPath;
@@ -63,6 +64,8 @@ public class WireMockSnippet implements Snippet {
private StubMapping stubMapping;
private boolean hasJsonBodyRequestToMatch = false;
@Override
public void document(Operation operation) throws IOException {
extractMatchers(operation);
@@ -81,7 +84,8 @@ public class WireMockSnippet implements Snippet {
}
private void extractMatchers(Operation operation) {
this.stubMapping = (StubMapping) operation.getAttributes().get("contract.stubMapping");
this.stubMapping = (StubMapping) operation.getAttributes()
.get("contract.stubMapping");
if (this.stubMapping != null) {
return;
}
@@ -89,7 +93,17 @@ public class WireMockSnippet implements Snippet {
Set<String> jsonPaths = (Set<String>) operation.getAttributes()
.get("contract.jsonPaths");
this.jsonPaths = jsonPaths;
this.contentType = (MediaType) operation.getAttributes().get("contract.contentType");
this.contentType = (MediaType) operation.getAttributes()
.get("contract.contentType");
if (this.contentType == null) {
this.hasJsonBodyRequestToMatch = hasJsonContentType(operation);
}
}
private boolean hasJsonContentType(Operation operation) {
return operation.getRequest().getHeaders().getContentType() != null
&& (operation.getRequest().getHeaders().getContentType()
.isCompatibleWith(MediaType.APPLICATION_JSON));
}
private ResponseDefinitionBuilder response(Operation operation) {
@@ -144,6 +158,9 @@ public class WireMockSnippet implements Snippet {
builder.withRequestBody(matchingJsonPath(jsonPath));
}
}
else if (this.hasJsonBodyRequestToMatch) {
builder.withRequestBody(equalToJson(content));
}
else {
builder.withRequestBody(equalTo(content));
}

View File

@@ -3,6 +3,7 @@ package org.springframework.cloud.contract.wiremock.restdocs;
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.util.Collection;
@@ -17,6 +18,7 @@ import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.restdocs.RestDocumentationContext;
import org.springframework.restdocs.operation.Operation;
import org.springframework.restdocs.operation.OperationRequest;
@@ -24,6 +26,7 @@ import org.springframework.restdocs.operation.OperationRequestPart;
import org.springframework.restdocs.operation.OperationResponse;
import org.springframework.restdocs.operation.Parameters;
import com.github.tomakehurst.wiremock.matching.EqualToJsonPattern;
import com.github.tomakehurst.wiremock.stubbing.StubMapping;
import static org.assertj.core.api.Assertions.assertThat;
@@ -36,9 +39,11 @@ import static org.mockito.Matchers.anyString;
@RunWith(MockitoJUnitRunner.class)
public class WireMockSnippetTests {
@Mock(answer = Answers.RETURNS_DEEP_STUBS) Operation operation;
@Rule public TemporaryFolder tmp = new TemporaryFolder();
File outputFolder;
@Mock(answer = Answers.RETURNS_DEEP_STUBS)
Operation operation;
@Rule
public TemporaryFolder tmp = new TemporaryFolder();
private File outputFolder;
@Before
public void setup() throws IOException {
@@ -46,13 +51,15 @@ public class WireMockSnippetTests {
}
@Test
public void should_maintain_the_response_status_when_generating_stub() throws Exception {
public void should_maintain_the_response_status_when_generating_stub()
throws Exception {
WireMockSnippet snippet = new WireMockSnippet();
RestDocumentationContext context = new RestDocumentationContext(this.getClass(),
"method", this.outputFolder);
given(this.operation.getName()).willReturn("foo");
given(this.operation.getAttributes().get(anyString())).willReturn(null);
given(this.operation.getAttributes().get(RestDocumentationContext.class.getName())).willReturn(context);
given(this.operation.getAttributes()
.get(RestDocumentationContext.class.getName())).willReturn(context);
given(this.operation.getRequest()).willReturn(request());
given(this.operation.getResponse()).willReturn(response());
@@ -60,26 +67,57 @@ public class WireMockSnippetTests {
File stub = new File(this.outputFolder, "stubs/foo.json");
assertThat(stub).exists();
StubMapping stubMapping = StubMapping.buildFrom(new String(Files.readAllBytes(stub.toPath())));
assertThat(stubMapping.getResponse().getStatus()).isEqualTo(HttpStatus.ACCEPTED.value());
StubMapping stubMapping = StubMapping
.buildFrom(new String(Files.readAllBytes(stub.toPath())));
assertThat(stubMapping.getResponse().getStatus())
.isEqualTo(HttpStatus.ACCEPTED.value());
}
@Test
public void should_use_equal_to_json_pattern_for_body_when_request_content_type_is_json_when_generating_stub()
throws Exception {
WireMockSnippet snippet = new WireMockSnippet();
RestDocumentationContext context = new RestDocumentationContext(this.getClass(),
"method", this.outputFolder);
given(this.operation.getName()).willReturn("foo");
given(this.operation.getAttributes().get(anyString())).willReturn(null);
given(this.operation.getAttributes()
.get(RestDocumentationContext.class.getName())).willReturn(context);
given(this.operation.getRequest()).willReturn(requestPostWithJsonContentType());
given(this.operation.getResponse()).willReturn(response());
snippet.document(this.operation);
File stub = new File(this.outputFolder, "stubs/foo.json");
assertThat(stub).exists();
StubMapping stubMapping = StubMapping
.buildFrom(new String(Files.readAllBytes(stub.toPath())));
assertThat(stubMapping.getRequest().getBodyPatterns().get(0))
.isInstanceOf(EqualToJsonPattern.class);
assertThat(stubMapping.getRequest().getBodyPatterns().get(0).getValue())
.isEqualTo("{\"name\": \"12\"}");
}
private OperationResponse response() {
return new OperationResponse() {
@Override public HttpStatus getStatus() {
@Override
public HttpStatus getStatus() {
return HttpStatus.ACCEPTED;
}
@Override public HttpHeaders getHeaders() {
@Override
public HttpHeaders getHeaders() {
return new HttpHeaders();
}
@Override public byte[] getContent() {
@Override
public byte[] getContent() {
return new byte[0];
}
@Override public String getContentAsString() {
@Override
public String getContentAsString() {
return null;
}
};
@@ -88,34 +126,83 @@ public class WireMockSnippetTests {
private OperationRequest request() {
return new OperationRequest() {
@Override public byte[] getContent() {
@Override
public byte[] getContent() {
return new byte[0];
}
@Override public String getContentAsString() {
@Override
public String getContentAsString() {
return null;
}
@Override public HttpHeaders getHeaders() {
@Override
public HttpHeaders getHeaders() {
return new HttpHeaders();
}
@Override public HttpMethod getMethod() {
@Override
public HttpMethod getMethod() {
return HttpMethod.GET;
}
@Override public Parameters getParameters() {
@Override
public Parameters getParameters() {
return null;
}
@Override public Collection<OperationRequestPart> getParts() {
@Override
public Collection<OperationRequestPart> getParts() {
return null;
}
@Override public URI getUri() {
@Override
public URI getUri() {
return URI.create("http://foo/bar");
}
};
}
private OperationRequest requestPostWithJsonContentType() {
return new OperationRequest() {
@Override
public byte[] getContent() {
String content = "{\"name\": \"12\"}";
return content.getBytes(Charset.forName("UTF-8"));
}
@Override
public String getContentAsString() {
return "{\"name\": \"12\"}";
}
@Override
public HttpHeaders getHeaders() {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add("Content-Type", MediaType.APPLICATION_JSON_VALUE);
return httpHeaders;
}
@Override
public HttpMethod getMethod() {
return HttpMethod.POST;
}
@Override
public Parameters getParameters() {
return null;
}
@Override
public Collection<OperationRequestPart> getParts() {
return null;
}
@Override
public URI getUri() {
return URI.create("http://foo/bar");
}
};
}
}