Merge branch '1.0.x'
This commit is contained in:
74
README.adoc
74
README.adoc
@@ -15,6 +15,8 @@ and consumers, for HTTP and message-based interactions.
|
||||
|
||||
:core_path: ../../../..
|
||||
:doc_samples: {core_path}/samples/wiremock-jetty
|
||||
:wiremock_tests: {core_path}/spring-cloud-contract-wiremock
|
||||
|
||||
|
||||
Modules giving you the possibility to use
|
||||
http://wiremock.org[WireMock] with different servers by using the
|
||||
@@ -321,6 +323,78 @@ available on the classpath, you can create a stub using WireMock in a
|
||||
number of different ways, including as described above using
|
||||
`@AutoConfigureWireMock(stubs="classpath:resource.json")`.
|
||||
|
||||
== Generating Contracts using RestDocs
|
||||
|
||||
Another thing that can be generated with Spring RestDocs is the Spring Cloud
|
||||
Contract DSL file and documentation. If you combine that with Spring Cloud
|
||||
WireMock then you're getting both the contracts and stubs.
|
||||
|
||||
TIP: You might wonder why this functionality is in the WireMock module.
|
||||
Come to think of it, it does make sense since it makes little sense to generate
|
||||
only contracts and not generate the stubs. That's why we suggest to do both.
|
||||
|
||||
Let's imagine the following test:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
this.mockMvc.perform(post("/foo")
|
||||
.accept(MediaType.APPLICATION_PDF)
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"foo\": 23 }"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("bar"))
|
||||
// first WireMock
|
||||
.andDo(WireMockRestDocs.verify()
|
||||
.jsonPath("$[?(@.foo >= 20)]")
|
||||
.contentType(MediaType.valueOf("application/json"))
|
||||
.stub("shouldGrantABeerIfOldEnough"))
|
||||
// then Contract DSL documentation
|
||||
.andDo(document("index", SpringCloudContractRestDocs.dslContract()));
|
||||
----
|
||||
|
||||
This will lead in the creation of the stub as presented in the previous
|
||||
section, contract will get generated and a documentation file too.
|
||||
|
||||
The contract will be called `index.groovy` and look more like this.
|
||||
|
||||
[souce,groovy]
|
||||
----
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
|
||||
Contract.make {
|
||||
request {
|
||||
method 'POST'
|
||||
url 'http://localhost:8080/foo'
|
||||
body('''
|
||||
{"foo": 23 }
|
||||
''')
|
||||
headers {
|
||||
header('''Accept''', '''application/json''')
|
||||
header('''Content-Type''', '''application/json''')
|
||||
header('''Host''', '''localhost:8080''')
|
||||
header('''Content-Length''', '''12''')
|
||||
}
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
body('''
|
||||
bar
|
||||
''')
|
||||
headers {
|
||||
header('''Content-Type''', '''application/json;charset=UTF-8''')
|
||||
header('''Content-Length''', '''3''')
|
||||
}
|
||||
testMatchers {
|
||||
jsonPath('$[?(@.foo >= 20)]', byType())
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
the generated document (example for Asciidoc) will contain a formatted contract
|
||||
(the location of this file would be `index/dsl-contract.adoc`).
|
||||
|
||||
=== Spring Cloud Contract Verifier
|
||||
|
||||
:introduction_url: https://raw.githubusercontent.com/spring-cloud/spring-cloud-contract/1.0.x
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
:core_path: ../../../..
|
||||
:doc_samples: {core_path}/samples/wiremock-jetty
|
||||
:wiremock_tests: {core_path}/spring-cloud-contract-wiremock
|
||||
|
||||
|
||||
Modules giving you the possibility to use
|
||||
http://wiremock.org[WireMock] with different servers by using the
|
||||
@@ -246,4 +248,63 @@ and `contentType()` methods to create request matchers, but not both.
|
||||
On the consumer side, assuming the `resource.json` generated above is
|
||||
available on the classpath, you can create a stub using WireMock in a
|
||||
number of different ways, including as described above using
|
||||
`@AutoConfigureWireMock(stubs="classpath:resource.json")`.
|
||||
`@AutoConfigureWireMock(stubs="classpath:resource.json")`.
|
||||
|
||||
== Generating Contracts using RestDocs
|
||||
|
||||
Another thing that can be generated with Spring RestDocs is the Spring Cloud
|
||||
Contract DSL file and documentation. If you combine that with Spring Cloud
|
||||
WireMock then you're getting both the contracts and stubs.
|
||||
|
||||
TIP: You might wonder why this functionality is in the WireMock module.
|
||||
Come to think of it, it does make sense since it makes little sense to generate
|
||||
only contracts and not generate the stubs. That's why we suggest to do both.
|
||||
|
||||
Let's imagine the following test:
|
||||
|
||||
[source,java]
|
||||
----
|
||||
include::{wiremock_tests}/src/test/java/org/springframework/cloud/contract/wiremock/restdocs/ContractDslSnippetTests.java[tags=contract_snippet]
|
||||
----
|
||||
|
||||
This will lead in the creation of the stub as presented in the previous
|
||||
section, contract will get generated and a documentation file too.
|
||||
|
||||
The contract will be called `index.groovy` and look more like this.
|
||||
|
||||
[souce,groovy]
|
||||
----
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
|
||||
Contract.make {
|
||||
request {
|
||||
method 'POST'
|
||||
url 'http://localhost:8080/foo'
|
||||
body('''
|
||||
{"foo": 23 }
|
||||
''')
|
||||
headers {
|
||||
header('''Accept''', '''application/json''')
|
||||
header('''Content-Type''', '''application/json''')
|
||||
header('''Host''', '''localhost:8080''')
|
||||
header('''Content-Length''', '''12''')
|
||||
}
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
body('''
|
||||
bar
|
||||
''')
|
||||
headers {
|
||||
header('''Content-Type''', '''application/json;charset=UTF-8''')
|
||||
header('''Content-Length''', '''3''')
|
||||
}
|
||||
testMatchers {
|
||||
jsonPath('$[?(@.foo >= 20)]', byType())
|
||||
}
|
||||
}
|
||||
}
|
||||
----
|
||||
|
||||
the generated document (example for Asciidoc) will contain a formatted contract
|
||||
(the location of this file would be `index/dsl-contract.adoc`).
|
||||
@@ -248,7 +248,7 @@ class Request extends Common {
|
||||
@CompileStatic
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
@ToString(includePackage = false)
|
||||
private class RequestHeaders extends Headers {
|
||||
class RequestHeaders extends Headers {
|
||||
|
||||
@Override
|
||||
DslProperty matching(String value) {
|
||||
|
||||
@@ -155,7 +155,7 @@ class Response extends Common {
|
||||
@CompileStatic
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
@ToString(includePackage = false)
|
||||
private class ResponseHeaders extends Headers {
|
||||
class ResponseHeaders extends Headers {
|
||||
|
||||
@Override
|
||||
DslProperty matching(String value) {
|
||||
|
||||
@@ -64,5 +64,10 @@
|
||||
<artifactId>spring-boot-configuration-processor</artifactId>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-verifier</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package org.springframework.cloud.contract.wiremock.restdocs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.restdocs.RestDocumentationContext;
|
||||
import org.springframework.restdocs.operation.Operation;
|
||||
import org.springframework.restdocs.operation.OperationRequest;
|
||||
import org.springframework.restdocs.operation.OperationResponse;
|
||||
import org.springframework.restdocs.snippet.TemplatedSnippet;
|
||||
import org.springframework.restdocs.templates.TemplateEngine;
|
||||
|
||||
/**
|
||||
* A {@link org.springframework.restdocs.snippet.Snippet} that documents the Spring Cloud Contract Groovy DSL.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.4
|
||||
*/
|
||||
public class ContractDslSnippet extends TemplatedSnippet {
|
||||
|
||||
private static final String CONTRACTS_FOLDER = "contracts";
|
||||
private static final String SNIPPET_NAME = "dsl-contract";
|
||||
|
||||
private Map<String, Object> model = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Creates a new {@code ContractDslSnippet} with no additional attributes.
|
||||
*/
|
||||
protected ContractDslSnippet() {
|
||||
this(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@code ContractDslSnippet} with the given additional
|
||||
* {@code attributes} that will be included in the model during template rendering.
|
||||
*
|
||||
* @param attributes The additional attributes
|
||||
*/
|
||||
protected ContractDslSnippet(Map<String, Object> attributes) {
|
||||
super(SNIPPET_NAME, attributes);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Map<String, Object> createModel(Operation operation) {
|
||||
return this.model;
|
||||
}
|
||||
|
||||
@Override public void document(Operation operation) throws IOException {
|
||||
TemplateEngine templateEngine = (TemplateEngine) operation.getAttributes().get(TemplateEngine.class.getName());
|
||||
String renderedContract = templateEngine.compileTemplate("default-dsl-contract-only")
|
||||
.render(createModelForContract(operation));
|
||||
this.model.put("contract", renderedContract);
|
||||
storeDslContract(operation, renderedContract);
|
||||
super.document(operation);
|
||||
}
|
||||
|
||||
private void insertResponseModel(Operation operation, Map<String, Object> model) {
|
||||
OperationResponse response = operation.getResponse();
|
||||
model.put("response_status", response.getStatus().value());
|
||||
model.put("response_body_present", response.getContent().length > 0);
|
||||
model.put("response_body", response.getContentAsString());
|
||||
HttpHeaders headers = response.getHeaders();
|
||||
model.put("response_headers_present", !headers.isEmpty());
|
||||
model.put("response_headers", headers.toSingleValueMap().entrySet());
|
||||
@SuppressWarnings("unchecked") Set<String> jsonPaths = (Set<String>) operation.getAttributes()
|
||||
.get("contract.jsonPaths");
|
||||
model.put("response_json_paths_present", jsonPaths != null && !jsonPaths.isEmpty());
|
||||
model.put("response_json_paths", jsonPaths(jsonPaths));
|
||||
}
|
||||
|
||||
private Set<JsonPaths> jsonPaths(Set<String> jsonPaths) {
|
||||
Set<JsonPaths> paths = new HashSet<>();
|
||||
if (jsonPaths == null) {
|
||||
return paths;
|
||||
}
|
||||
for (String s : jsonPaths) {
|
||||
paths.add(new JsonPaths(s));
|
||||
}
|
||||
return paths;
|
||||
}
|
||||
|
||||
private void insertRequestModel(Operation operation, Map<String, Object> model) {
|
||||
OperationRequest request = operation.getRequest();
|
||||
model.put("request_method", request.getMethod());
|
||||
model.put("request_url", request.getUri());
|
||||
model.put("request_body_present", request.getContent().length > 0);
|
||||
model.put("request_body", request.getContentAsString());
|
||||
HttpHeaders headers = request.getHeaders();
|
||||
model.put("request_headers_present", !headers.isEmpty());
|
||||
model.put("request_headers", headers.toSingleValueMap().entrySet());
|
||||
}
|
||||
|
||||
private Map<String, Object> createModelForContract(Operation operation) {
|
||||
Map<String, Object> modelForContract = new HashMap<>();
|
||||
insertRequestModel(operation, modelForContract);
|
||||
insertResponseModel(operation, modelForContract);
|
||||
return modelForContract;
|
||||
}
|
||||
|
||||
private void storeDslContract(Operation operation, String content)
|
||||
throws IOException {
|
||||
RestDocumentationContext context = (RestDocumentationContext) operation
|
||||
.getAttributes().get(RestDocumentationContext.class.getName());
|
||||
File output = new File(context.getOutputDirectory(),
|
||||
CONTRACTS_FOLDER + "/" + operation.getName() + ".groovy");
|
||||
output.getParentFile().mkdirs();
|
||||
try (Writer writer = new OutputStreamWriter(new FileOutputStream(output))) {
|
||||
writer.append(content);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class JsonPaths {
|
||||
private final String jsonPath;
|
||||
|
||||
JsonPaths(String jsonPath) {
|
||||
this.jsonPath = jsonPath;
|
||||
}
|
||||
|
||||
public String getJsonPath() {
|
||||
return this.jsonPath;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2012-2015 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.contract.wiremock.restdocs;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.restdocs.snippet.Snippet;
|
||||
|
||||
/**
|
||||
* Convenience class for setting up RestDocs to generate a {@link org.springframework.restdocs.snippet.Snippet}
|
||||
* with Spring Cloud Contract DSL. Example usage:
|
||||
*
|
||||
* <pre>
|
||||
* @RunWith(SpringRunner.class)
|
||||
* @SpringBootTest
|
||||
* @AutoConfigureRestDocs(outputDir = "target/snippets")
|
||||
* @AutoConfigureMockMvc
|
||||
* public class ContractRestDocsApplicationTests {
|
||||
*
|
||||
* @Autowired
|
||||
* private MockMvc mockMvc;
|
||||
*
|
||||
* @Test
|
||||
* public void contextLoads() throws Exception {
|
||||
* this.mockMvc.perform(post("/foo")
|
||||
* .accept(MediaType.APPLICATION_PDF)
|
||||
* .accept(MediaType.APPLICATION_JSON)
|
||||
* .contentType(MediaType.APPLICATION_JSON)
|
||||
* .content("{\"foo\": 23 }"))
|
||||
* .andExpect(status().isOk())
|
||||
* .andExpect(content().string("bar"))
|
||||
* // first WireMock
|
||||
* .andDo(WireMockRestDocs.verify()
|
||||
* .jsonPath("$[?(@.foo >= 20)]")
|
||||
* .contentType(MediaType.valueOf("application/json"))
|
||||
* .stub("shouldGrantABeerIfOldEnough"))
|
||||
* // then Contract DSL documentation
|
||||
* .andDo(document("index", SpringCloudContractRestDocs.dslContract()));
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* which creates a file "target/snippets/contracts/index.groovy" and a
|
||||
* standard documentation entitled `dsl-contract.adoc` containing that contract.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.4
|
||||
*/
|
||||
public class SpringCloudContractRestDocs {
|
||||
|
||||
private SpringCloudContractRestDocs() {
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code Snippet} that will document Spring Cloud Contract DSL for the API
|
||||
* operation.
|
||||
*
|
||||
* @return the snippet that will document the Spring Cloud Contract DSL
|
||||
*/
|
||||
public static Snippet dslContract() {
|
||||
return new ContractDslSnippet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new {@code Snippet} that will document the Spring Cloud Contract DSL for the API
|
||||
* operation. The given {@code attributes} will be available during snippet
|
||||
* generation.
|
||||
*
|
||||
* @param attributes the attributes
|
||||
* @return the snippet that will document the Spring Cloud Contract DSL
|
||||
*/
|
||||
public static Snippet dslContract(Map<String, Object> attributes) {
|
||||
return new ContractDslSnippet(attributes);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
[source,groovy]
|
||||
----
|
||||
{{contract}}
|
||||
----
|
||||
@@ -0,0 +1,42 @@
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
|
||||
Contract.make {
|
||||
request {
|
||||
method '{{request_method}}'
|
||||
url '{{request_url}}'
|
||||
{{#request_body_present}}
|
||||
body('''
|
||||
{{request_body}}
|
||||
''')
|
||||
{{/request_body_present}}
|
||||
{{#request_headers_present}}
|
||||
headers {
|
||||
{{#request_headers}}
|
||||
header('''{{key}}''', '''{{value}}''')
|
||||
{{/request_headers}}
|
||||
}
|
||||
{{/request_headers_present}}
|
||||
}
|
||||
response {
|
||||
status {{response_status}}
|
||||
{{#response_body_present}}
|
||||
body('''
|
||||
{{response_body}}
|
||||
''')
|
||||
{{/response_body_present}}
|
||||
{{#response_headers_present}}
|
||||
headers {
|
||||
{{#response_headers}}
|
||||
header('''{{key}}''', '''{{value}}''')
|
||||
{{/response_headers}}
|
||||
}
|
||||
{{/response_headers_present}}
|
||||
{{#response_json_paths_present}}
|
||||
testMatchers {
|
||||
{{#response_json_paths}}
|
||||
jsonPath('{{jsonPath}}', byType())
|
||||
{{/response_json_paths}}
|
||||
}
|
||||
{{/response_json_paths_present}}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
```groovy
|
||||
{{contract}}
|
||||
```
|
||||
@@ -0,0 +1,137 @@
|
||||
package org.springframework.cloud.contract.wiremock.restdocs;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
|
||||
import org.springframework.boot.test.context.SpringBootTest;
|
||||
import org.springframework.cloud.contract.spec.Contract;
|
||||
import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.http.MediaType;
|
||||
import org.springframework.restdocs.JUnitRestDocumentation;
|
||||
import org.springframework.test.context.junit4.SpringRunner;
|
||||
import org.springframework.test.web.servlet.MockMvc;
|
||||
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
|
||||
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.context.WebApplicationContext;
|
||||
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
import static org.springframework.cloud.contract.wiremock.restdocs.SpringCloudContractRestDocs.dslContract;
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.document;
|
||||
import static org.springframework.restdocs.mockmvc.MockMvcRestDocumentation.documentationConfiguration;
|
||||
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content;
|
||||
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@RunWith(SpringRunner.class)
|
||||
@SpringBootTest(classes = ContractDslSnippetTests.Config.class)
|
||||
public class ContractDslSnippetTests {
|
||||
|
||||
private static final String OUTPUT = "target/generated-snippets";
|
||||
@Rule
|
||||
public JUnitRestDocumentation restDocumentation = new JUnitRestDocumentation(OUTPUT);
|
||||
|
||||
MockMvc mockMvc;
|
||||
@Autowired WebApplicationContext context;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
this.mockMvc = MockMvcBuilders.webAppContextSetup(this.context)
|
||||
.apply(documentationConfiguration(this.restDocumentation))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_create_contract_template_and_doc() throws Exception {
|
||||
//tag::contract_snippet[]
|
||||
this.mockMvc.perform(post("/foo")
|
||||
.accept(MediaType.APPLICATION_PDF)
|
||||
.accept(MediaType.APPLICATION_JSON)
|
||||
.contentType(MediaType.APPLICATION_JSON)
|
||||
.content("{\"foo\": 23 }"))
|
||||
.andExpect(status().isOk())
|
||||
.andExpect(content().string("bar"))
|
||||
// first WireMock
|
||||
.andDo(WireMockRestDocs.verify()
|
||||
.jsonPath("$[?(@.foo >= 20)]")
|
||||
.contentType(MediaType.valueOf("application/json"))
|
||||
.stub("shouldGrantABeerIfOldEnough"))
|
||||
// then Contract DSL documentation
|
||||
.andDo(document("index", SpringCloudContractRestDocs.dslContract()));
|
||||
//end::contract_snippet[]
|
||||
|
||||
then(file("/contracts/index.groovy")).exists();
|
||||
then(file("/index/dsl-contract.adoc")).exists();
|
||||
String contract = readFromFile(file("/contracts/index.groovy"));
|
||||
// try to parse the contract
|
||||
Contract parsedContract = ContractVerifierDslConverter.convert(contract);
|
||||
then(parsedContract.getRequest().getHeaders().getEntries()).isNotEmpty();
|
||||
then(parsedContract.getRequest().getMethod().getClientValue()).isNotNull();
|
||||
then(parsedContract.getRequest().getUrl().getClientValue()).isNotNull();
|
||||
then(parsedContract.getRequest().getBody().getClientValue()).isNotNull();
|
||||
then(parsedContract.getResponse().getStatus().getClientValue()).isNotNull();
|
||||
then(parsedContract.getResponse().getHeaders().getEntries()).isNotEmpty();
|
||||
then(parsedContract.getResponse().getBody().getClientValue()).isNotNull();
|
||||
then(parsedContract.getResponse().getMatchers().hasMatchers()).isTrue();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void should_create_contract_template_and_doc_without_body_and_headers() throws Exception {
|
||||
this.mockMvc.perform(MockMvcRequestBuilders.get("/foo"))
|
||||
.andExpect(status().isOk())
|
||||
.andDo(document("empty", dslContract()));
|
||||
|
||||
then(file("/contracts/empty.groovy")).exists();
|
||||
then(file("/empty/dsl-contract.adoc")).exists();
|
||||
String contract = readFromFile(file("/contracts/empty.groovy"));
|
||||
// try to parse the contract
|
||||
Contract parsedContract = ContractVerifierDslConverter.convert(contract);
|
||||
then(parsedContract.getRequest().getHeaders().getEntries()).isNotEmpty();
|
||||
then(parsedContract.getRequest().getMethod().getClientValue()).isNotNull();
|
||||
then(parsedContract.getRequest().getUrl().getClientValue()).isNotNull();
|
||||
then(parsedContract.getRequest().getBody()).isNull();
|
||||
then(parsedContract.getResponse().getStatus().getClientValue()).isNotNull();
|
||||
then(parsedContract.getResponse().getHeaders()).isNull();
|
||||
then(parsedContract.getResponse().getBody()).isNull();
|
||||
then(parsedContract.getResponse().getMatchers()).isNull();
|
||||
}
|
||||
|
||||
private File file(String name) throws URISyntaxException {
|
||||
return new File(OUTPUT, name);
|
||||
}
|
||||
|
||||
private String readFromFile(File f) throws IOException {
|
||||
byte[] encoded = Files.readAllBytes(f.toPath());
|
||||
return new String(encoded, StandardCharsets.UTF_8);
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableAutoConfiguration
|
||||
@RestController
|
||||
static class Config {
|
||||
|
||||
@PostMapping("/foo")
|
||||
String foo() {
|
||||
return "bar";
|
||||
}
|
||||
|
||||
@GetMapping("/foo")
|
||||
void getFoo() {
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user