Added equality check to matchers
This commit is contained in:
@@ -255,6 +255,8 @@ part of your contract. The other is called `testMatchers` which is present in th
|
||||
Currently we support only JSON Path based matchers with the following matching possibilities.
|
||||
For `stubMatchers`:
|
||||
|
||||
- `byValue(...)` - the value taken from the response via the provided JSON Path needs
|
||||
to be equal to the provided value
|
||||
- `byRegex(...)` - the value taken from the response via the provided JSON Path needs
|
||||
to match the regex
|
||||
- `byDate()` - the value taken from the response via the provided JSON Path needs to
|
||||
@@ -266,6 +268,8 @@ match the regex for ISO Time
|
||||
|
||||
For `testMatchers`:
|
||||
|
||||
- `byValue(...)` - the value taken from the response via the provided JSON Path needs
|
||||
to be equal to the provided value
|
||||
- `byRegex(...)` - the value taken from the response via the provided JSON Path needs
|
||||
to match the regex
|
||||
- `byDate()` - the value taken from the response via the provided JSON Path needs to
|
||||
@@ -307,36 +311,38 @@ assertions and the one from matchers with an `and` section):
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
// given:
|
||||
MockMvcRequestSpecification request = given()
|
||||
.header("Content-Type", "application/json")
|
||||
.body("{\"duck\":123,\"alpha\":\"abc\",\"number\":123,\"aBoolean\":true,\"date\":\"2017-01-01\",\"dateTime\":\"2017-01-01T01:23:45\",\"time\":\"01:02:34\",\"valueWithoutAMatcher\":\"foo\",\"valueWithTypeMatch\":\"string\"}");
|
||||
// given:
|
||||
MockMvcRequestSpecification request = given()
|
||||
.header("Content-Type", "application/json")
|
||||
.body("{\"duck\":123,\"alpha\":\"abc\",\"number\":123,\"aBoolean\":true,\"date\":\"2017-01-01\",\"dateTime\":\"2017-01-01T01:23:45\",\"time\":\"01:02:34\",\"valueWithoutAMatcher\":\"foo\",\"valueWithTypeMatch\":\"string\"}");
|
||||
|
||||
// when:
|
||||
ResponseOptions response = given().spec(request)
|
||||
.get("/get");
|
||||
// when:
|
||||
ResponseOptions response = given().spec(request)
|
||||
.get("/get");
|
||||
|
||||
// then:
|
||||
assertThat(response.statusCode()).isEqualTo(200);
|
||||
assertThat(response.header("Content-Type")).matches("application/json.*");
|
||||
// and:
|
||||
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
|
||||
assertThatJson(parsedJson).field("valueWithoutAMatcher").isEqualTo("foo");
|
||||
// and:
|
||||
assertThat(parsedJson.read("$.duck", String.class)).matches("[0-9]{3}");
|
||||
assertThat(parsedJson.read("$.alpha", String.class)).matches("[\\p{L}]*");
|
||||
assertThat(parsedJson.read("$.number", String.class)).matches("-?\\d*(\\.\\d+)?");
|
||||
assertThat(parsedJson.read("$.aBoolean", String.class)).matches("(true|false)");
|
||||
assertThat(parsedJson.read("$.date", String.class)).matches("(\\d\\d\\d\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])");
|
||||
assertThat(parsedJson.read("$.dateTime", String.class)).matches("([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])");
|
||||
assertThat(parsedJson.read("$.time", String.class)).matches("(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])");
|
||||
assertThat((Object) parsedJson.read("$.valueWithTypeMatch")).isInstanceOf(class java.lang.String.class);
|
||||
assertThat((Object) parsedJson.read("$.valueWithMin")).isInstanceOf(java.util.List.class);
|
||||
assertThat(parsedJson.read("$.valueWithMin", java.util.Collection.class).size()).isLessThanOrEqualTo(1);
|
||||
assertThat((Object) parsedJson.read("$.valueWithMax")).isInstanceOf(java.util.List.class);
|
||||
assertThat(parsedJson.read("$.valueWithMax", java.util.Collection.class).size()).isGreaterThanOrEqualTo(3);
|
||||
assertThat((Object) parsedJson.read("$.valueWithMinMax")).isInstanceOf(java.util.List.class);
|
||||
assertThat(parsedJson.read("$.valueWithMinMax", java.util.Collection.class).size()).isStrictlyBetween(1, 3);
|
||||
// then:
|
||||
assertThat(response.statusCode()).isEqualTo(200);
|
||||
assertThat(response.header("Content-Type")).matches("application/json.*");
|
||||
// and:
|
||||
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
|
||||
assertThatJson(parsedJson).field("valueWithoutAMatcher").isEqualTo("foo");
|
||||
// and:
|
||||
assertThat(parsedJson.read("$.duck", String.class)).matches("[0-9]{3}");
|
||||
assertThat(parsedJson.read("$.duck", Integer.class)).isEqualTo(123);
|
||||
assertThat(parsedJson.read("$.alpha", String.class)).matches("[\\p{L}]*");
|
||||
assertThat(parsedJson.read("$.alpha", String.class)).isEqualTo("abc");
|
||||
assertThat(parsedJson.read("$.number", String.class)).matches("-?\\d*(\\.\\d+)?");
|
||||
assertThat(parsedJson.read("$.aBoolean", String.class)).matches("(true|false)");
|
||||
assertThat(parsedJson.read("$.date", String.class)).matches("(\\d\\d\\d\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])");
|
||||
assertThat(parsedJson.read("$.dateTime", String.class)).matches("([0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])");
|
||||
assertThat(parsedJson.read("$.time", String.class)).matches("(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])");
|
||||
assertThat((Object) parsedJson.read("$.valueWithTypeMatch")).isInstanceOf(java.lang.String.class);
|
||||
assertThat((Object) parsedJson.read("$.valueWithMin")).isInstanceOf(java.util.List.class);
|
||||
assertThat(parsedJson.read("$.valueWithMin", java.util.Collection.class).size()).isLessThanOrEqualTo(1);
|
||||
assertThat((Object) parsedJson.read("$.valueWithMax")).isInstanceOf(java.util.List.class);
|
||||
assertThat(parsedJson.read("$.valueWithMax", java.util.Collection.class).size()).isGreaterThanOrEqualTo(3);
|
||||
assertThat((Object) parsedJson.read("$.valueWithMinMax")).isInstanceOf(java.util.List.class);
|
||||
assertThat(parsedJson.read("$.valueWithMinMax", java.util.Collection.class).size()).isStrictlyBetween(1, 3);
|
||||
----
|
||||
|
||||
and the WireMock stub like this:
|
||||
|
||||
@@ -25,7 +25,7 @@ interface BodyMatcher {
|
||||
* by type, the defined response body contained an integer but the actual one
|
||||
* contained a string then the assertion should fail
|
||||
*/
|
||||
String value()
|
||||
Object value()
|
||||
|
||||
/**
|
||||
* Min no of occurrence when matching by type. In all other cases it will be ignored
|
||||
|
||||
@@ -46,6 +46,11 @@ class BodyMatchers {
|
||||
return new MatchingTypeValue(MatchingType.REGEX, regex)
|
||||
}
|
||||
|
||||
MatchingTypeValue byValue(Object value) {
|
||||
assert value
|
||||
return new MatchingTypeValue(MatchingType.EQUALITY, value)
|
||||
}
|
||||
|
||||
boolean equals(o) {
|
||||
if (this.is(o)) return true
|
||||
if (this.getClass() != o.class) return false
|
||||
@@ -81,7 +86,7 @@ class JsonPathBodyMatcher implements BodyMatcher {
|
||||
}
|
||||
|
||||
@Override
|
||||
String value() {
|
||||
Object value() {
|
||||
return this.matchingTypeValue.value
|
||||
}
|
||||
|
||||
@@ -106,9 +111,9 @@ class MatchingTypeValue {
|
||||
MatchingType type
|
||||
|
||||
/**
|
||||
* Value of regular expression
|
||||
* Value to check
|
||||
*/
|
||||
String value
|
||||
Object value
|
||||
|
||||
/**
|
||||
* Min occurrence when matching by type
|
||||
|
||||
@@ -77,7 +77,7 @@ class StubRunnerCamelPredicate implements Predicate {
|
||||
}
|
||||
if (matchers != null && matchers.hasMatchers()) {
|
||||
for (BodyMatcher matcher : matchers.jsonPathMatchers()) {
|
||||
String jsonPath = JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher.path(), matcher.value());
|
||||
String jsonPath = JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher);
|
||||
matches &= matchesJsonPath(parsedJson, jsonPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ class StubRunnerIntegrationMessageSelector implements MessageSelector {
|
||||
}
|
||||
if (matchers != null && matchers.hasMatchers()) {
|
||||
for (BodyMatcher matcher : matchers.jsonPathMatchers()) {
|
||||
String jsonPath = JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher.path(), matcher.value());
|
||||
String jsonPath = JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher);
|
||||
matches &= matchesJsonPath(parsedJson, jsonPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,7 +76,7 @@ class StubRunnerStreamMessageSelector implements MessageSelector {
|
||||
}
|
||||
if (matchers != null && matchers.hasMatchers()) {
|
||||
for (BodyMatcher matcher : matchers.jsonPathMatchers()) {
|
||||
String jsonPath = JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher.path(), matcher.value());
|
||||
String jsonPath = JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher);
|
||||
matches &= matchesJsonPath(parsedJson, jsonPath);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.contract.verifier.wiremock
|
||||
|
||||
import com.github.tomakehurst.wiremock.matching.RegexPattern
|
||||
import com.github.tomakehurst.wiremock.stubbing.StubMapping
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TemporaryFolder
|
||||
@@ -24,6 +25,8 @@ import org.springframework.cloud.contract.verifier.file.ContractMetadata
|
||||
import spock.lang.Issue
|
||||
import spock.lang.Specification
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
class DslToWireMockClientConverterSpec extends Specification {
|
||||
|
||||
@Rule
|
||||
@@ -51,6 +54,8 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
JSONAssert.assertEquals('''
|
||||
{"request":{"method":"PUT","urlPattern":"/[0-9]{2}"},"response":{"status":200}}
|
||||
''', json, false)
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(json)
|
||||
}
|
||||
|
||||
@Issue("196")
|
||||
@@ -82,6 +87,8 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
"status":200,"fixedDelayMilliseconds":1000
|
||||
}}
|
||||
''', json, false)
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(json)
|
||||
}
|
||||
|
||||
def "should convert DSL file with a nested list to WireMock JSON"() {
|
||||
@@ -186,6 +193,8 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
}
|
||||
}
|
||||
''', json, false)
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(json)
|
||||
}
|
||||
|
||||
|
||||
@@ -222,6 +231,8 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
JSONAssert.assertEquals('''
|
||||
{"request":{"urlPath":"/foos","method":"GET"},"response":{"body":"[{\\"id\\":\\"123\\"},{\\"id\\":\\"567\\"}]"}}
|
||||
''', json, false)
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(json)
|
||||
}
|
||||
|
||||
|
||||
@@ -248,11 +259,12 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
""")
|
||||
when:
|
||||
String json = converter.convertContent("test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
StubMapping.buildFrom(json)
|
||||
then:
|
||||
noExceptionThrown()
|
||||
and:
|
||||
!json.contains('cursor')
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(json)
|
||||
}
|
||||
|
||||
def 'should convert dsl to wiremock to show it in the docs'() {
|
||||
@@ -287,9 +299,9 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
}
|
||||
''')
|
||||
when:
|
||||
String json = converter.convertContent("Test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
String json = converter.convertContent("Test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
then:
|
||||
JSONAssert.assertEquals( // tag::wiremock[]
|
||||
JSONAssert.assertEquals( // tag::wiremock[]
|
||||
'''
|
||||
{
|
||||
"request" : {
|
||||
@@ -318,14 +330,16 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
'''
|
||||
// end::wiremock[]
|
||||
, json, false)
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(json)
|
||||
}
|
||||
|
||||
def 'should convert dsl to wiremock with stub matchers'() {
|
||||
given:
|
||||
def converter = new DslToWireMockClientConverter()
|
||||
def converter = new DslToWireMockClientConverter()
|
||||
and:
|
||||
File file = tmpFolder.newFile("dsl_from_docs.groovy")
|
||||
file.write('''
|
||||
File file = tmpFolder.newFile("dsl_from_docs.groovy")
|
||||
file.write('''
|
||||
org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
method 'GET'
|
||||
@@ -357,7 +371,9 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
])
|
||||
stubMatchers {
|
||||
jsonPath('$.duck', byRegex("[0-9]{3}"))
|
||||
jsonPath('$.duck', byValue(123))
|
||||
jsonPath('$.alpha', byRegex(onlyAlphaUnicode()))
|
||||
jsonPath('$.alpha', byValue("abc"))
|
||||
jsonPath('$.number', byRegex(number()))
|
||||
jsonPath('$.aBoolean', byRegex(anyBoolean()))
|
||||
jsonPath('$.date', byDate())
|
||||
@@ -394,8 +410,10 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
testMatchers {
|
||||
// asserts the jsonpath value against manual regex
|
||||
jsonPath('$.duck', byRegex("[0-9]{3}"))
|
||||
jsonPath('$.duck', byValue(123))
|
||||
// asserts the jsonpath value against some default regex
|
||||
jsonPath('$.alpha', byRegex(onlyAlphaUnicode()))
|
||||
jsonPath('$.alpha', byValue("abc"))
|
||||
jsonPath('$.number', byRegex(number()))
|
||||
jsonPath('$.aBoolean', byRegex(anyBoolean()))
|
||||
// asserts vs inbuilt time related regex
|
||||
@@ -425,9 +443,9 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
}
|
||||
''')
|
||||
when:
|
||||
String json = converter.convertContent("Test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
String json = converter.convertContent("Test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
then:
|
||||
JSONAssert.assertEquals(//tag::matchers[]
|
||||
JSONAssert.assertEquals(//tag::matchers[]
|
||||
'''
|
||||
{
|
||||
"request" : {
|
||||
@@ -450,8 +468,12 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
"matchesJsonPath" : "$.list.someother.nested[?(@.json == 'with value')]"
|
||||
}, {
|
||||
"matchesJsonPath" : "$[?(@.duck =~ /([0-9]{3})/)]"
|
||||
}, {
|
||||
"matchesJsonPath" : "$[?(@.duck == 123)]"
|
||||
}, {
|
||||
"matchesJsonPath" : "$[?(@.alpha =~ /([\\\\p{L}]*)/)]"
|
||||
}, {
|
||||
"matchesJsonPath" : "$[?(@.alpha == 'abc')]"
|
||||
}, {
|
||||
"matchesJsonPath" : "$[?(@.number =~ /(-?\\\\d*(\\\\.\\\\d+)?)/)]"
|
||||
}, {
|
||||
@@ -477,6 +499,8 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
'''
|
||||
//end::matchers[]
|
||||
, json, false)
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(json)
|
||||
}
|
||||
|
||||
def 'should convert dsl to wiremock with stub matchers with docs example'() {
|
||||
@@ -549,6 +573,16 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
}
|
||||
'''
|
||||
, json, false)
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(json)
|
||||
}
|
||||
|
||||
void stubMappingIsValidWireMockStub(String mappingDefinition) {
|
||||
StubMapping stubMapping = StubMapping.buildFrom(mappingDefinition)
|
||||
stubMapping.request.bodyPatterns.findAll { it.isPresent() && it instanceof RegexPattern }.every {
|
||||
Pattern.compile(it.getValue())
|
||||
}
|
||||
assert !mappingDefinition.contains('org.springframework.cloud.contract.spec.internal')
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -312,7 +312,11 @@ abstract class MethodBodyBuilder {
|
||||
// for the rest we'll do JsonPath matching in brute force
|
||||
bodyMatchers.jsonPathMatchers().each {
|
||||
if (it.value()) {
|
||||
String method = "assertThat(parsedJson.read(${quotedAndEscaped(it.path())}, String.class)).matches(${quotedAndEscaped(it.value())})"
|
||||
String comparisonMethod = it.matchingType() == MatchingType.EQUALITY ? "isEqualTo" : "matches"
|
||||
String valueAsParam = it.value() instanceof String ? quotedAndEscaped(it.value().toString()) : it.value().toString()
|
||||
String classToCastTo = "${it.value().class.simpleName}.class"
|
||||
String path = quotedAndEscaped(it.path())
|
||||
String method = "assertThat(parsedJson.read(${path}, ${classToCastTo})).${comparisonMethod}(${valueAsParam})"
|
||||
bb.addLine(postProcessJsonPathCall(method))
|
||||
addColonIfRequired(bb)
|
||||
} else {
|
||||
|
||||
@@ -87,7 +87,7 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
}
|
||||
if (request.matchers?.hasMatchers()) {
|
||||
request.matchers.jsonPathMatchers().each {
|
||||
String newPath = JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(it.path(), it.value())
|
||||
String newPath = JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(it)
|
||||
requestPattern.withRequestBody(WireMock.matchingJsonPath(newPath.replace("\\\\", "\\")))
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,15 +21,14 @@ import com.toomuchcoding.jsonassert.JsonAssertion
|
||||
import groovy.json.JsonOutput
|
||||
import groovy.json.JsonSlurper
|
||||
import groovy.util.logging.Slf4j
|
||||
import org.springframework.cloud.contract.spec.internal.OptionalProperty
|
||||
import org.springframework.cloud.contract.spec.internal.BodyMatcher
|
||||
import org.springframework.cloud.contract.spec.internal.BodyMatchers
|
||||
import org.springframework.cloud.contract.spec.internal.MatchingType
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.spec.internal.MatchingType
|
||||
import org.springframework.cloud.contract.spec.internal.OptionalProperty
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
|
||||
import java.util.regex.Pattern
|
||||
|
||||
/**
|
||||
* I would like to apologize to anyone who is reading this class. Since JSON is a hectic structure
|
||||
* this class is also hectic. The idea is to traverse the JSON structure and build a set of
|
||||
@@ -73,8 +72,7 @@ class JsonToJsonPathsConverter {
|
||||
*/
|
||||
static def removeMatchingJsonPaths(def json, BodyMatchers bodyMatchers) {
|
||||
if (bodyMatchers?.hasMatchers()) {
|
||||
// remove all jsonpaths from the body - for those that remain we continue as usual
|
||||
bodyMatchers.jsonPathMatchers().findAll { it.matchingType() != MatchingType.EQUALITY }.each { BodyMatcher matcher ->
|
||||
bodyMatchers.jsonPathMatchers().each { BodyMatcher matcher ->
|
||||
JsonPath.parse(json).delete(matcher.path())
|
||||
}
|
||||
}
|
||||
@@ -82,21 +80,32 @@ class JsonToJsonPathsConverter {
|
||||
}
|
||||
|
||||
/**
|
||||
* For the given JSON path and regex pattern converts it into a JSON path
|
||||
* that checks the Pattern
|
||||
* For the given matcher converts it into a JSON path
|
||||
* that checks the regex pattern or equality
|
||||
*
|
||||
* @param path - JSON path
|
||||
* @param pattern - pattern to check for the last element of JSON path
|
||||
* @param bodyMatcher
|
||||
* @return JSON path that checks the regex for its last element
|
||||
*/
|
||||
static String convertJsonPathAndRegexToAJsonPath(String path, String pattern) {
|
||||
if (!pattern) {
|
||||
static String convertJsonPathAndRegexToAJsonPath(BodyMatcher bodyMatcher) {
|
||||
String path = bodyMatcher.path()
|
||||
Object value = bodyMatcher.value()
|
||||
if (!value) {
|
||||
return path
|
||||
}
|
||||
int lastIndexOfDot = path.lastIndexOf(".")
|
||||
String toLastDot = path.substring(0, lastIndexOfDot)
|
||||
String fromLastDot = path.substring(lastIndexOfDot + 1)
|
||||
return "${toLastDot}[?(@.${fromLastDot} =~ /(${pattern})/)]"
|
||||
String comparison = createComparison(bodyMatcher, value)
|
||||
return "${toLastDot}[?(@.${fromLastDot} ${comparison})]"
|
||||
}
|
||||
|
||||
private static String createComparison(BodyMatcher bodyMatcher, Object value) {
|
||||
if (bodyMatcher.matchingType() == MatchingType.EQUALITY) {
|
||||
String wrappedValue = value instanceof Number ? value : "'${value.toString()}'"
|
||||
return "== ${wrappedValue}"
|
||||
} else {
|
||||
return "=~ /(${value})/"
|
||||
}
|
||||
}
|
||||
|
||||
JsonPaths transformToJsonPathWithTestsSideValues(def json) {
|
||||
|
||||
@@ -51,7 +51,9 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
|
||||
])
|
||||
stubMatchers {
|
||||
jsonPath('$.duck', byRegex("[0-9]{3}"))
|
||||
jsonPath('$.duck', byValue(123))
|
||||
jsonPath('$.alpha', byRegex(onlyAlphaUnicode()))
|
||||
jsonPath('$.alpha', byValue("abc"))
|
||||
jsonPath('$.number', byRegex(number()))
|
||||
jsonPath('$.aBoolean', byRegex(anyBoolean()))
|
||||
jsonPath('$.date', byDate())
|
||||
@@ -87,8 +89,11 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
|
||||
testMatchers {
|
||||
// asserts the jsonpath value against manual regex
|
||||
jsonPath('$.duck', byRegex("[0-9]{3}"))
|
||||
// asserts the jsonpath value against the provided value
|
||||
jsonPath('$.duck', byValue(123))
|
||||
// asserts the jsonpath value against some default regex
|
||||
jsonPath('$.alpha', byRegex(onlyAlphaUnicode()))
|
||||
jsonPath('$.alpha', byValue("abc"))
|
||||
jsonPath('$.number', byRegex(number()))
|
||||
jsonPath('$.aBoolean', byRegex(anyBoolean()))
|
||||
// asserts vs inbuilt time related regex
|
||||
@@ -124,7 +129,9 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements
|
||||
def test = blockBuilder.toString()
|
||||
then:
|
||||
test.contains('assertThat(parsedJson.read("' + rootElement + '.duck", String.class)).matches("[0-9]{3}")')
|
||||
test.contains('assertThat(parsedJson.read("' + rootElement + '.duck", Integer.class)).isEqualTo(123)')
|
||||
test.contains('assertThat(parsedJson.read("' + rootElement + '.alpha", String.class)).matches("[\\\\p{L}]*")')
|
||||
test.contains('assertThat(parsedJson.read("' + rootElement + '.alpha", String.class)).isEqualTo("abc")')
|
||||
test.contains('assertThat(parsedJson.read("' + rootElement + '.number", String.class)).matches("-?\\\\d*(\\\\.\\\\d+)?")')
|
||||
test.contains('assertThat(parsedJson.read("' + rootElement + '.aBoolean", String.class)).matches("(true|false)")')
|
||||
test.contains('assertThat(parsedJson.read("' + rootElement + '.date", String.class)).matches("(\\\\d\\\\d\\\\d\\\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])")')
|
||||
|
||||
@@ -24,6 +24,8 @@ import com.toomuchcoding.jsonassert.JsonAssertion
|
||||
import groovy.json.JsonOutput
|
||||
import groovy.json.JsonSlurper
|
||||
import net.minidev.json.JSONArray
|
||||
import org.springframework.cloud.contract.spec.internal.BodyMatcher
|
||||
import org.springframework.cloud.contract.spec.internal.MatchingType
|
||||
import spock.lang.Specification
|
||||
import spock.util.environment.RestoreSystemProperties
|
||||
|
||||
@@ -758,14 +760,59 @@ class JsonToJsonPathsConverterSpec extends Specification {
|
||||
String jsonPath = '$.a.b.c.d'
|
||||
String regexPattern = ".*"
|
||||
expect:
|
||||
'$.a.b.c[?(@.d =~ /(.*)/)]' == JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(jsonPath, regexPattern)
|
||||
'$.a.b.c[?(@.d =~ /(.*)/)]' == JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher(MatchingType.REGEX, jsonPath, regexPattern))
|
||||
}
|
||||
|
||||
def "should return the path if no regex pattern is provided"() {
|
||||
def "should convert a json path with value to a equality checking json path without quotes for numbers"() {
|
||||
given:
|
||||
String jsonPath = '$.a.b.c.d'
|
||||
Integer value = 1234
|
||||
expect:
|
||||
'$.a.b.c[?(@.d == 1234)]' == JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher(MatchingType.EQUALITY, jsonPath, value))
|
||||
}
|
||||
|
||||
def "should convert a json path with value to a equality checking json path with quotes for strings"() {
|
||||
given:
|
||||
String jsonPath = '$.a.b.c.d'
|
||||
String value = "foo"
|
||||
expect:
|
||||
'$.a.b.c[?(@.d == \'foo\')]' == JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher(MatchingType.EQUALITY, jsonPath, value))
|
||||
}
|
||||
|
||||
def "should return the path if no value is provided"() {
|
||||
given:
|
||||
String jsonPath = '$.a.b.c.d'
|
||||
expect:
|
||||
'$.a.b.c.d' == JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(jsonPath, null)
|
||||
'$.a.b.c.d' == JsonToJsonPathsConverter.convertJsonPathAndRegexToAJsonPath(matcher(MatchingType.REGEX, jsonPath, null))
|
||||
}
|
||||
|
||||
private BodyMatcher matcher(final MatchingType matchingType, final String jsonPath, final Object value) {
|
||||
return new BodyMatcher() {
|
||||
@Override
|
||||
MatchingType matchingType() {
|
||||
return matchingType
|
||||
}
|
||||
|
||||
@Override
|
||||
String path() {
|
||||
return jsonPath
|
||||
}
|
||||
|
||||
@Override
|
||||
Object value() {
|
||||
return value
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer minTypeOccurrence() {
|
||||
return null
|
||||
}
|
||||
|
||||
@Override
|
||||
Integer maxTypeOccurrence() {
|
||||
return null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void assertThatJsonPathsInMapAreValid(String json, JsonPaths pathAndValues) {
|
||||
|
||||
Reference in New Issue
Block a user