Added pact evaluation of $.body type matcher

fixes #511
This commit is contained in:
Marcin Grzejszczak
2018-01-12 15:24:15 +01:00
parent 709df3e291
commit bea0d4f78d
6 changed files with 132 additions and 12 deletions

View File

@@ -21,8 +21,9 @@ import org.springframework.cloud.contract.spec.internal.ExecutionProperty
import org.springframework.cloud.contract.spec.internal.Headers
import org.springframework.cloud.contract.spec.internal.MatchingType
import org.springframework.cloud.contract.spec.internal.QueryParameters
import org.springframework.cloud.contract.verifier.util.JsonPaths
import org.springframework.cloud.contract.verifier.util.JsonToJsonPathsConverter
import org.springframework.cloud.contract.verifier.util.MapConverter
/**
* Converter of JSON PACT file
*
@@ -36,6 +37,7 @@ class PactContractConverter implements ContractConverter<Pact> {
private static final String REGEX_KEY = "regex"
private static final String MAX_KEY = "max"
private static final String MIN_KEY = "min"
private static final String FULL_BODY = '$.body'
@Override
boolean isAccepted(File file) {
@@ -90,7 +92,8 @@ class PactContractConverter implements ContractConverter<Pact> {
}
if (requestResponseInteraction.request?.matchingRules) {
stubMatchers {
requestResponseInteraction.request.matchingRules.each { String key, Map<String, Object> value ->
Map<String, Map<String, Object>> rules = requestResponseInteraction.request.matchingRules
rules.each { String key, Map<String, Object> value ->
String keyFromBody = toKeyStartingFromBody(key)
if (value.containsKey(MATCH_KEY)) {
MatchingType matchingType = MatchingType.valueOf((value.get(MATCH_KEY) as String).toUpperCase())
@@ -132,8 +135,19 @@ class PactContractConverter implements ContractConverter<Pact> {
}
if (requestResponseInteraction.response?.matchingRules) {
testMatchers {
requestResponseInteraction.response.matchingRules.each { String key, Map<String, Object> value ->
Map<String, Map<String, Object>> rules = requestResponseInteraction.response.matchingRules
Map<String, Object> fullBodyCheck = rules.get(FULL_BODY)
if (fullBodyCheck != null) {
JsonPaths jsonPaths = JsonToJsonPathsConverter.transformToJsonPathWithStubsSideValuesAndNoArraySizeCheck(requestResponseInteraction.request?.body?.value)
jsonPaths.each {
jsonPath(it.keyBeforeChecking(), byType())
}
}
rules.each { String key, Map<String, Object> value ->
String keyFromBody = toKeyStartingFromBody(key)
if (!keyFromBody) {
return
}
if (value.containsKey(MATCH_KEY)) {
MatchingType matchingType = MatchingType.valueOf((value.get(MATCH_KEY) as String).toUpperCase())
switch (matchingType) {
@@ -185,7 +199,10 @@ class PactContractConverter implements ContractConverter<Pact> {
}
protected String toKeyStartingFromBody(String key) {
return key.replace('$.body', '$')
if (key == FULL_BODY) {
return ""
}
return key.replace(FULL_BODY, '$')
}
@Override

View File

@@ -8,6 +8,7 @@ import org.springframework.cloud.contract.spec.Contract
import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter
import org.springframework.core.io.Resource
import org.springframework.core.io.support.PathMatchingResourcePatternResolver
import spock.lang.Issue
import spock.lang.Specification
import spock.lang.Subject
/**
@@ -16,6 +17,7 @@ import spock.lang.Subject
class PactContractConverterSpec extends Specification {
File pactJson = new File(PactContractConverterSpec.getResource("/pact/pact.json").toURI())
File pact509Json = new File(PactContractConverterSpec.getResource("/pact/pact_509.json").toURI())
@Subject PactContractConverter converter = new PactContractConverter()
def "should accept json files that are pact files"() {
@@ -76,6 +78,37 @@ class PactContractConverterSpec extends Specification {
contracts == [expectedContract]
}
@Issue("#509")
def "should convert from pact with matching rules to whole body to contract"() {
given:
Contract expectedContract = Contract.make {
description("a request to POST a person provider accepts a new person")
request {
method(POST())
url("/user-service/users")
headers {
contentType(applicationJson())
}
body(firstName: "Arthur", lastName: "Dent")
}
response {
status(201)
headers {
contentType(applicationJson())
}
body(id: 42)
testMatchers {
jsonPath('''$.['lastName']''', byType())
jsonPath('''$.['firstName']''', byType())
}
}
}
when:
Collection<Contract> contracts = converter.convertFrom(pact509Json)
then:
contracts == [expectedContract]
}
def "should convert from contract to pact"() {
given:
Collection<Contract> inputContracts = [

View File

@@ -0,0 +1,44 @@
{
"consumer": {
"name": "ui"
},
"provider": {
"name": "userservice"
},
"interactions": [
{
"description": "a request to POST a person",
"providerState": "provider accepts a new person",
"request": {
"method": "POST",
"path": "/user-service/users",
"headers": {
"Content-Type": "application/json"
},
"body": {
"firstName": "Arthur",
"lastName": "Dent"
}
},
"response": {
"status": 201,
"headers": {
"Content-Type": "application/json;charset=UTF-8"
},
"body": {
"id": 42
},
"matchingRules": {
"$.body": {
"match": "type"
}
}
}
}
],
"metadata": {
"pactSpecification": {
"version": "2.0.0"
}
}
}