@@ -72,7 +72,7 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
|
||||
requestPattern.bodyPatterns = [new ValuePattern(jsonCompareMode: org.skyscreamer.jsonassert.JSONCompareMode.LENIENT,
|
||||
equalToJson: JsonOutput.toJson(getMatchingStrategy(request.body.clientValue).clientValue) ) ]
|
||||
} else {
|
||||
requestPattern.bodyPatterns = values.collect { new ValuePattern(matchesJsonPath: it.jsonPath().replace("\\\\", "\\")) } ?: null as List<ValuePattern>
|
||||
requestPattern.bodyPatterns = values.findAll{ !it.assertsSize() }.collect { new ValuePattern(matchesJsonPath: it.jsonPath().replace("\\\\", "\\")) } ?: null as List<ValuePattern>
|
||||
}
|
||||
} else if (contentType == ContentType.XML) {
|
||||
requestPattern.bodyPatterns = [new ValuePattern(equalToXml: getMatchingStrategy(request.body.clientValue).clientValue.toString())]
|
||||
|
||||
@@ -1,8 +1,9 @@
|
||||
package io.codearte.accurest.util;
|
||||
|
||||
import com.toomuchcoding.jsonassert.JsonVerifiable;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.toomuchcoding.jsonassert.JsonVerifiable;
|
||||
|
||||
import static org.apache.commons.lang3.StringEscapeUtils.escapeJava;
|
||||
|
||||
@@ -11,18 +12,21 @@ import static org.apache.commons.lang3.StringEscapeUtils.escapeJava;
|
||||
*/
|
||||
class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
private final JsonVerifiable delegate;
|
||||
private final LinkedList<String> methodsBuffer;
|
||||
private static final Pattern FIELD_PATTERN = Pattern.compile("\\.field\\((\")?(.)+(\")?\\)");
|
||||
private static final Pattern ARRAY_PATTERN = Pattern.compile("\\.array\\((\")?(.)+(\")?\\)");
|
||||
|
||||
final JsonVerifiable delegate;
|
||||
final LinkedList<String> methodsBuffer;
|
||||
|
||||
DelegatingJsonVerifiable(JsonVerifiable delegate,
|
||||
LinkedList<String> methodsBuffer) {
|
||||
this.delegate = delegate;
|
||||
this.methodsBuffer = new LinkedList<String>(methodsBuffer);
|
||||
this.methodsBuffer = new LinkedList<>(methodsBuffer);
|
||||
}
|
||||
|
||||
DelegatingJsonVerifiable(JsonVerifiable delegate) {
|
||||
this.delegate = delegate;
|
||||
this.methodsBuffer = new LinkedList<String>();
|
||||
this.methodsBuffer = new LinkedList<>();
|
||||
}
|
||||
|
||||
private static String stringWithEscapedQuotes(Object object) {
|
||||
@@ -32,7 +36,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
private static String wrapValueWithQuotes(Object value) {
|
||||
return value instanceof String ?
|
||||
"\"" + stringWithEscapedQuotes((String) value) + "\"" :
|
||||
"\"" + stringWithEscapedQuotes(value) + "\"" :
|
||||
value.toString();
|
||||
}
|
||||
|
||||
@@ -103,6 +107,13 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
return verifiable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonVerifiable elementWithIndex(int i) {
|
||||
DelegatingJsonVerifiable verifiable = new DelegatingJsonVerifiable(delegate.elementWithIndex(i), methodsBuffer);
|
||||
verifiable.methodsBuffer.offer(".elementWithIndex(" + i + ")");
|
||||
return verifiable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodBufferingJsonVerifiable iterationPassingArray() {
|
||||
return new DelegatingJsonVerifiable(delegate, methodsBuffer);
|
||||
@@ -183,6 +194,26 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
return new FinishedDelegatingJsonVerifiable(delegate, methodsBuffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertsSize() {
|
||||
for (String s : methodsBuffer) {
|
||||
if (s.contains(".hasSize(")) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean assertsConcreteValue() {
|
||||
for (String s : methodsBuffer) {
|
||||
if (FIELD_PATTERN.matcher(s).matches()|| ARRAY_PATTERN.matcher(s).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonVerifiable withoutThrowingException() {
|
||||
return delegate.withoutThrowingException();
|
||||
@@ -198,6 +229,13 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
delegate.matchesJsonPath(s);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonVerifiable hasSize(int size) {
|
||||
FinishedDelegatingJsonVerifiable verifiable = new FinishedDelegatingJsonVerifiable(delegate.hasSize(size), methodsBuffer);
|
||||
verifiable.methodsBuffer.offer(".hasSize(" + size + ")");
|
||||
return verifiable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIteratingOverNamelessArray() {
|
||||
return delegate.isIteratingOverNamelessArray();
|
||||
@@ -219,7 +257,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
}
|
||||
|
||||
private String createMethodString() {
|
||||
LinkedList<String> queue = new LinkedList<String>(methodsBuffer);
|
||||
LinkedList<String> queue = new LinkedList<>(methodsBuffer);
|
||||
StringBuilder stringBuffer = new StringBuilder();
|
||||
while (!queue.isEmpty()) {
|
||||
stringBuffer.append(queue.remove());
|
||||
@@ -238,17 +276,19 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
|
||||
|
||||
if (delegate != null ? !delegate.equals(that.delegate) : that.delegate != null)
|
||||
return false;
|
||||
return methodsBuffer != null ?
|
||||
methodsBuffer.equals(that.methodsBuffer) :
|
||||
that.methodsBuffer == null;
|
||||
if (delegate == null) {
|
||||
return false;
|
||||
}
|
||||
if (delegate.jsonPath() == null && that.delegate.jsonPath() == null)
|
||||
return true;
|
||||
return delegate.jsonPath().equals(that.delegate.jsonPath());
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = delegate != null ? delegate.hashCode() : 0;
|
||||
result = 31 * result + (methodsBuffer != null ? methodsBuffer.hashCode() : 0);
|
||||
return result;
|
||||
int result = delegate != null ? delegate.jsonPath().hashCode() : 0;
|
||||
return 31 * result;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
package io.codearte.accurest.util;
|
||||
|
||||
import com.toomuchcoding.jsonassert.JsonVerifiable;
|
||||
|
||||
import java.util.LinkedList;
|
||||
|
||||
import com.toomuchcoding.jsonassert.JsonVerifiable;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
@@ -14,8 +14,4 @@ class FinishedDelegatingJsonVerifiable extends DelegatingJsonVerifiable {
|
||||
super(delegate, methodsBuffer);
|
||||
}
|
||||
|
||||
FinishedDelegatingJsonVerifiable(JsonVerifiable delegate) {
|
||||
super(delegate, new LinkedList<String>());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -7,11 +7,22 @@ import io.codearte.accurest.dsl.internal.ExecutionProperty
|
||||
import io.codearte.accurest.dsl.internal.OptionalProperty
|
||||
|
||||
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
|
||||
* JSON Paths together with methods needed to be called to build them.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*/
|
||||
class JsonToJsonPathsConverter {
|
||||
|
||||
/**
|
||||
* In case of issues with size assertion just provide this property as system property
|
||||
* equal to "false" and then size assertion will be disabled
|
||||
*/
|
||||
private static final String SIZE_ASSERTION_SYSTEM_PROP = "accurest.assert.size"
|
||||
|
||||
private static final Boolean SERVER_SIDE = false
|
||||
private static final Boolean CLIENT_SIDE = true
|
||||
|
||||
@@ -61,18 +72,21 @@ class JsonToJsonPathsConverter {
|
||||
return convertWithKey(Map, key, value as Map, closure)
|
||||
// JSON with a list of primitives ["a", "b", "c"] in root issue #266
|
||||
} else if (key.isIteratingOverNamelessArray() && value instanceof List && listContainsOnlyPrimitives(value)) {
|
||||
addSizeVerificationForListWithPrimitives(key, closure, value)
|
||||
value.each {
|
||||
traverseRecursively(Object, key.arrayField().contains(ContentUtils.returnParsedObject(it)),
|
||||
ContentUtils.returnParsedObject(it), closure)
|
||||
}
|
||||
// JSON containing list of primitives { "partners":[ { "role":"AGENT", "payment_methods":[ "BANK", "CASH" ] } ]
|
||||
} else if (value instanceof List && listContainsOnlyPrimitives(value)) {
|
||||
addSizeVerificationForListWithPrimitives(key, closure, value)
|
||||
value.each {
|
||||
traverseRecursively(Object, valueToAsserter(key.arrayField(), ContentUtils.returnParsedObject(it)),
|
||||
ContentUtils.returnParsedObject(it), closure)
|
||||
}
|
||||
} else if (value instanceof List) {
|
||||
MethodBufferingJsonVerifiable jsonPathVerifiable = createAsserterFromList(key, value)
|
||||
addSizeVerificationForListWithPrimitives(key, closure, value)
|
||||
value.each { def element ->
|
||||
traverseRecursively(List, createAsserterFromListElement(jsonPathVerifiable, ContentUtils.returnParsedObject(element)),
|
||||
ContentUtils.returnParsedObject(element), closure)
|
||||
@@ -89,6 +103,23 @@ class JsonToJsonPathsConverter {
|
||||
}
|
||||
}
|
||||
|
||||
// Size verification: https://github.com/Codearte/accurest/issues/279
|
||||
private static void addSizeVerificationForListWithPrimitives(MethodBufferingJsonVerifiable key, Closure closure, List value) {
|
||||
if (System.getProperty(SIZE_ASSERTION_SYSTEM_PROP, "true") == "false") {
|
||||
return
|
||||
}
|
||||
if (isRootElement(key) || key.assertsConcreteValue()) {
|
||||
if (value.size() > 0) {
|
||||
closure(key.hasSize(value.size()), value)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean isRootElement(MethodBufferingJsonVerifiable key) {
|
||||
return key.jsonPath() == '$'
|
||||
}
|
||||
|
||||
// If you have a list of not-only primitives it can contain different sets of elements (maps, lists, primitives)
|
||||
private static MethodBufferingJsonVerifiable createAsserterFromList(MethodBufferingJsonVerifiable key, List value) {
|
||||
if (key.isIteratingOverNamelessArray()) {
|
||||
return key.array()
|
||||
|
||||
@@ -46,4 +46,8 @@ public interface MethodBufferingJsonVerifiable
|
||||
|
||||
@Override
|
||||
MethodBufferingJsonVerifiable value();
|
||||
|
||||
boolean assertsSize();
|
||||
|
||||
boolean assertsConcreteValue();
|
||||
}
|
||||
|
||||
@@ -98,6 +98,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub
|
||||
then:
|
||||
blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""")
|
||||
blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("a").isEqualTo("sth")""")
|
||||
blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").hasSize(2)""")
|
||||
blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("b").isEqualTo("sthElse")""")
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new Contract(null, false, 0, null), contractDsl).toWireMockClientStub())
|
||||
|
||||
@@ -166,6 +166,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub
|
||||
then:
|
||||
blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""")
|
||||
blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("a").isEqualTo("sth")""")
|
||||
blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").hasSize(2)""")
|
||||
blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("b").isEqualTo("sthElse")""")
|
||||
and:
|
||||
stubMappingIsValidWireMockStub(contractDsl)
|
||||
@@ -1251,6 +1252,7 @@ World.'''"""
|
||||
builder.then(blockBuilder)
|
||||
def test = blockBuilder.toString()
|
||||
then:
|
||||
test.contains('assertThatJson(parsedJson).hasSize(5)')
|
||||
test.contains('assertThatJson(parsedJson).arrayField().contains("Java8").value()')
|
||||
test.contains('assertThatJson(parsedJson).arrayField().contains("Spring").value()')
|
||||
test.contains('assertThatJson(parsedJson).arrayField().contains("Java").value()')
|
||||
@@ -1284,6 +1286,7 @@ World.'''"""
|
||||
builder.then(blockBuilder)
|
||||
def test = blockBuilder.toString()
|
||||
then:
|
||||
test.contains('assertThatJson(parsedJson).hasSize(2)')
|
||||
test.contains('assertThatJson(parsedJson).array().arrayField().isEqualTo("Programming").value()')
|
||||
test.contains('assertThatJson(parsedJson).array().arrayField().isEqualTo("Java").value()')
|
||||
test.contains('assertThatJson(parsedJson).array().arrayField().isEqualTo("Spring").value()')
|
||||
@@ -1293,6 +1296,7 @@ World.'''"""
|
||||
"MockMvcSpockMethodBuilder" | { GroovyDsl dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl) }
|
||||
"MockMvcJUnitMethodBuilder" | { GroovyDsl dsl -> new MockMvcJUnitMethodBodyBuilder(dsl) }
|
||||
}
|
||||
|
||||
@Issue('47')
|
||||
def "should generate async body when async flag set in response"() {
|
||||
given:
|
||||
|
||||
@@ -353,12 +353,16 @@ class JsonToJsonPathsConverterSpec extends Specification {
|
||||
it.method()== """.array("property2").contains("a").isEqualTo("sth")""" &&
|
||||
it.jsonPath() == """\$.property2[*][?(@.a == 'sth')]"""
|
||||
}
|
||||
pathAndValues.find {
|
||||
it.method()== """.array("property2").hasSize(2)""" &&
|
||||
it.jsonPath() == """\$.property2[*]"""
|
||||
}
|
||||
pathAndValues.find {
|
||||
it.method()== """.array("property2").contains("b").isEqualTo("sthElse")""" &&
|
||||
it.jsonPath() == """\$.property2[*][?(@.b == 'sthElse')]"""
|
||||
}
|
||||
and:
|
||||
pathAndValues.size() == 3
|
||||
pathAndValues.size() == 4
|
||||
}
|
||||
|
||||
def "should generate assertions for a response body containing map with integers as keys"() {
|
||||
@@ -404,8 +408,12 @@ class JsonToJsonPathsConverterSpec extends Specification {
|
||||
it.method()== """.array().contains("property2").isEqualTo("b")""" &&
|
||||
it.jsonPath() == """\$[*][?(@.property2 == 'b')]"""
|
||||
}
|
||||
pathAndValues.find {
|
||||
it.method()== """.hasSize(2)""" &&
|
||||
it.jsonPath() == """\$"""
|
||||
}
|
||||
and:
|
||||
pathAndValues.size() == 2
|
||||
pathAndValues.size() == 3
|
||||
}
|
||||
|
||||
def "should generate assertions for array inside response body element"() {
|
||||
@@ -427,8 +435,12 @@ class JsonToJsonPathsConverterSpec extends Specification {
|
||||
it.method()== """.array("property1").contains("property3").isEqualTo("test2")""" &&
|
||||
it.jsonPath() == """\$.property1[*][?(@.property3 == 'test2')]"""
|
||||
}
|
||||
pathAndValues.find {
|
||||
it.method()== """.array("property1").hasSize(2)""" &&
|
||||
it.jsonPath() == """\$.property1[*]"""
|
||||
}
|
||||
and:
|
||||
pathAndValues.size() == 2
|
||||
pathAndValues.size() == 3
|
||||
}
|
||||
|
||||
def "should generate assertions for nested objects in response body"() {
|
||||
@@ -509,8 +521,12 @@ class JsonToJsonPathsConverterSpec extends Specification {
|
||||
it.method()== """.array("errors").contains("message").isEqualTo("incorrect_format")""" &&
|
||||
it.jsonPath() == """\$.errors[*][?(@.message == 'incorrect_format')]"""
|
||||
}
|
||||
pathAndValues.find {
|
||||
it.method()== """.array("errors").hasSize(1)""" &&
|
||||
it.jsonPath() == """\$.errors[*]"""
|
||||
}
|
||||
and:
|
||||
pathAndValues.size() == 2
|
||||
pathAndValues.size() == 3
|
||||
}
|
||||
|
||||
def "should manage to parse a double array"() {
|
||||
@@ -549,8 +565,20 @@ class JsonToJsonPathsConverterSpec extends Specification {
|
||||
it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().arrayField().isEqualTo(38.791645)""" &&
|
||||
it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*][?(@ == 38.791645)]"""
|
||||
}
|
||||
pathAndValues.find {
|
||||
it.method()== """.hasSize(1)""" &&
|
||||
it.jsonPath() == """\$"""
|
||||
}
|
||||
pathAndValues.find {
|
||||
it.method()== """.array().field("place").field("bounding_box").array("coordinates").array().hasSize(2)""" &&
|
||||
it.jsonPath() == """\$[*].place.bounding_box.coordinates[*][*]"""
|
||||
}
|
||||
pathAndValues.find {
|
||||
it.method()== """.array().field("place").field("bounding_box").array("coordinates").hasSize(1)""" &&
|
||||
it.jsonPath() == """\$[*].place.bounding_box.coordinates[*]"""
|
||||
}
|
||||
and:
|
||||
pathAndValues.size() == 4
|
||||
pathAndValues.size() == 7
|
||||
and:
|
||||
pathAndValues.each {
|
||||
JsonAssertion.assertThat(json).matchesJsonPath(it.jsonPath())
|
||||
|
||||
@@ -2,7 +2,7 @@ nexusUsername =
|
||||
nexusPassword =
|
||||
|
||||
wiremockVersion = 2.0.10-beta
|
||||
jsonassertVersion = 0.4.5
|
||||
jsonassertVersion = 0.4.7
|
||||
|
||||
BOM_VERSION=Brixton-1.0.0.RC1
|
||||
springBootVersion=1.3.3.RELEASE
|
||||
|
||||
Reference in New Issue
Block a user