Added Contract converter + Yaml example
This commit is contained in:
@@ -0,0 +1,40 @@
|
||||
package org.springframework.cloud.contract.spec;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Converter to be used to convert FROM {@link File} TO {@link Contract}
|
||||
* and from {@link Contract} to {@link T}
|
||||
*
|
||||
* @param <T> - type to which we want to convert the contract
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.3
|
||||
*/
|
||||
public interface ContractConverter<T> {
|
||||
|
||||
/**
|
||||
* Should this file be accepted by the converter. Can use the file extension
|
||||
* to check if the conversion is possible.
|
||||
*
|
||||
* @param file - file to be considered for conversion
|
||||
* @return - {@code true} if the given implementation can convert the file
|
||||
*/
|
||||
boolean isAccepted(File file);
|
||||
|
||||
/**
|
||||
* Converts the given {@link File} to its {@link Contract} representation
|
||||
*
|
||||
* @param file - file to convert
|
||||
* @return - {@link Contract} representation of the file
|
||||
*/
|
||||
Contract convertFrom(File file);
|
||||
|
||||
/**
|
||||
* Converts the given {@link Contract} to a {@link T} representation
|
||||
*
|
||||
* @param contract - the parsed contract
|
||||
* @return - {@link T} the type to which we do the conversion
|
||||
*/
|
||||
T convertTo(Contract contract);
|
||||
}
|
||||
@@ -18,6 +18,10 @@
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-spec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-verifier</artifactId>
|
||||
@@ -34,6 +38,11 @@
|
||||
<groupId>com.github.tomakehurst</groupId>
|
||||
<artifactId>wiremock</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.yaml</groupId>
|
||||
<artifactId>snakeyaml</artifactId>
|
||||
<scope>optional</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.spockframework</groupId>
|
||||
<artifactId>spock-core</artifactId>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package org.springframework.cloud.contract.verifier.dsl;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Yaml representation of a {@link org.springframework.cloud.contract.spec.Contract}
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.3
|
||||
*/
|
||||
//TODO: Perform full conversion
|
||||
public class YamlContract {
|
||||
public Request request = new Request();
|
||||
public Response response = new Response();
|
||||
|
||||
static class Request {
|
||||
public String method;
|
||||
public String url;
|
||||
public Map<String, Object> headers = new HashMap<>();
|
||||
public Map<String, Object> body = new HashMap<>();
|
||||
}
|
||||
|
||||
static class Response {
|
||||
public int status;
|
||||
public Map<String, Object> headers = new HashMap<>();
|
||||
public Map<String, Object> body = new HashMap<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.springframework.cloud.contract.verifier.dsl
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.ContractConverter
|
||||
import org.springframework.cloud.contract.spec.internal.Headers
|
||||
import org.yaml.snakeyaml.Yaml
|
||||
|
||||
/**
|
||||
* Converter from and to a {@link YamlContract} to a
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 1.0.3
|
||||
*/
|
||||
//TODO: Perform full conversion
|
||||
@CompileStatic
|
||||
class YamlContractConverter implements ContractConverter<YamlContract> {
|
||||
|
||||
@Override
|
||||
public boolean isAccepted(File file) {
|
||||
String name = file.getName()
|
||||
return name.endsWith(".yml") || name.endsWith(".yaml")
|
||||
}
|
||||
|
||||
@Override
|
||||
public Contract convertFrom(File file) {
|
||||
try {
|
||||
YamlContract yamlContract = new Yaml().loadAs(new FileInputStream(file), YamlContract.class)
|
||||
return Contract.make {
|
||||
request {
|
||||
method(yamlContract.request.method)
|
||||
url(yamlContract.request.url)
|
||||
headers {
|
||||
yamlContract.request.headers.each { String key, Object value ->
|
||||
header(key, value)
|
||||
}
|
||||
}
|
||||
body(yamlContract.request.body)
|
||||
}
|
||||
response {
|
||||
status(yamlContract.response.status)
|
||||
headers {
|
||||
yamlContract.response.headers.each { String key, Object value ->
|
||||
header(key, value)
|
||||
}
|
||||
}
|
||||
body(yamlContract.response.body)
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException e) {
|
||||
throw new IllegalStateException(e)
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public YamlContract convertTo(Contract contract) {
|
||||
// TODO: Pick one of the sides - consumer / producer
|
||||
YamlContract yamlContract = new YamlContract()
|
||||
yamlContract.request.with {
|
||||
method = contract.request.method.clientValue
|
||||
url = contract.request.url.clientValue
|
||||
headers = (contract.request.headers as Headers).asStubSideMap()
|
||||
body = contract.request.body.clientValue as Map
|
||||
}
|
||||
yamlContract.response.with {
|
||||
status = contract.response.status.clientValue as Integer
|
||||
headers = (contract.response.headers as Headers).asStubSideMap()
|
||||
body = contract.response.body.clientValue as Map
|
||||
}
|
||||
return yamlContract
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
package org.springframework.cloud.contract.verifier.dsl
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import spock.lang.Specification
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
class YamlContractConverterSpec extends Specification {
|
||||
|
||||
URL ymlUrl = YamlContractConverterSpec.getResource("/contract.yml")
|
||||
File yml = new File(ymlUrl.toURI())
|
||||
YamlContractConverter converter = new YamlContractConverter()
|
||||
|
||||
def "should convert YAML to DSL"() {
|
||||
given:
|
||||
assert converter.isAccepted(yml)
|
||||
when:
|
||||
Contract contract = converter.convertFrom(yml)
|
||||
then:
|
||||
contract.request.url.clientValue == "/foo"
|
||||
contract.request.method.clientValue == "PUT"
|
||||
contract.request.headers.entries.find { it.name == "foo" && it.clientValue == "bar" }
|
||||
contract.request.body.clientValue == [foo: "bar"]
|
||||
contract.response.status.clientValue == 200
|
||||
contract.response.headers.entries.find { it.name == "foo2" && it.clientValue == "bar" }
|
||||
contract.response.body.clientValue == [foo2: "bar"]
|
||||
}
|
||||
|
||||
def "should convert DSL to YAML"() {
|
||||
given:
|
||||
assert converter.isAccepted(yml)
|
||||
and:
|
||||
Contract contract = Contract.make {
|
||||
request {
|
||||
url("/foo")
|
||||
method("PUT")
|
||||
headers {
|
||||
header("foo", "bar")
|
||||
}
|
||||
body([foo: "bar"])
|
||||
}
|
||||
response {
|
||||
status(200)
|
||||
headers {
|
||||
header("foo2", "bar")
|
||||
}
|
||||
body([foo2: "bar"])
|
||||
}
|
||||
}
|
||||
when:
|
||||
YamlContract yamlContract = converter.convertTo(contract)
|
||||
then:
|
||||
yamlContract.request.url == "/foo"
|
||||
yamlContract.request.method == "PUT"
|
||||
yamlContract.request.headers.find { it.key == "foo" && it.value == "bar" }
|
||||
yamlContract.request.body == [foo: "bar"]
|
||||
yamlContract.response.status == 200
|
||||
yamlContract.response.headers.find { it.key == "foo2" && it.value == "bar" }
|
||||
yamlContract.response.body == [foo2: "bar"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
request:
|
||||
url: /foo
|
||||
method: PUT
|
||||
headers:
|
||||
foo: bar
|
||||
body:
|
||||
foo: bar
|
||||
response:
|
||||
status: 200
|
||||
headers:
|
||||
foo2: bar
|
||||
body:
|
||||
foo2: bar
|
||||
@@ -17,6 +17,10 @@
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-spec</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-core</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-test-autoconfigure</artifactId>
|
||||
|
||||
@@ -82,7 +82,7 @@ class ContractFileScanner {
|
||||
files.sort().eachWithIndex { File file, int index ->
|
||||
boolean excluded = matchesPattern(file, excludeMatchers)
|
||||
if (!excluded) {
|
||||
boolean contractFile = isContractFile(file);
|
||||
boolean contractFile = isContractFile(file)
|
||||
boolean included = includeMatcher ? file.absolutePath.matches(includeMatcher) : true
|
||||
if (contractFile && included) {
|
||||
Path path = file.toPath()
|
||||
|
||||
Reference in New Issue
Block a user