Asserting empty array in the response (#211)

with this change we're using new JSONAssert that allows to check if an array is empty

fixes #203
This commit is contained in:
Marcin Grzejszczak
2017-02-02 13:24:10 +01:00
parent 87ec2a0f62
commit 79c6a2e72c
11 changed files with 76 additions and 17 deletions

View File

@@ -15,7 +15,7 @@
<description>Spring Cloud Contract Dependencies</description>
<properties>
<wiremock.version>2.1.7</wiremock.version>
<jsonassert.version>0.4.7</jsonassert.version>
<jsonassert.version>0.4.8</jsonassert.version>
<aether.version>1.0.2.v20150114</aether.version>
</properties>
<dependencyManagement>

View File

@@ -94,7 +94,7 @@ class SpringCloudContractVerifierGradlePlugin implements Plugin<Project> {
private void addProjectDependencies(Project project) {
//TODO: Consider removing this at some point
project.dependencies.add("testCompile", "com.github.tomakehurst:wiremock:2.1.7")
project.dependencies.add("testCompile", "com.toomuchcoding.jsonassert:jsonassert:0.4.7")
project.dependencies.add("testCompile", "com.toomuchcoding.jsonassert:jsonassert:0.4.8")
project.dependencies.add("testCompile", "org.assertj:assertj-core:2.3.0")
}

View File

@@ -63,7 +63,7 @@
<dependency>
<groupId>com.toomuchcoding.jsonassert</groupId>
<artifactId>jsonassert</artifactId>
<version>0.4.7</version>
<version>0.4.8</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@@ -63,7 +63,7 @@
<dependency>
<groupId>com.toomuchcoding.jsonassert</groupId>
<artifactId>jsonassert</artifactId>
<version>0.4.7</version>
<version>0.4.8</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@@ -64,7 +64,7 @@
<dependency>
<groupId>com.toomuchcoding.jsonassert</groupId>
<artifactId>jsonassert</artifactId>
<version>0.4.7</version>
<version>0.4.8</version>
<scope>test</scope>
</dependency>
<!-- end::dependencies[] -->

View File

@@ -63,7 +63,7 @@
<dependency>
<groupId>com.toomuchcoding.jsonassert</groupId>
<artifactId>jsonassert</artifactId>
<version>0.4.7</version>
<version>0.4.8</version>
<scope>test</scope>
</dependency>
<dependency>

View File

@@ -92,7 +92,7 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
def originalBody = getMatchingStrategyFromBody(request.body)?.clientValue
def body = JsonToJsonPathsConverter.removeMatchingJsonPaths(originalBody, request.matchers)
JsonPaths values = JsonToJsonPathsConverter.transformToJsonPathWithStubsSideValuesAndNoArraySizeCheck(body)
if (values.empty && !request.matchers?.hasMatchers()) {
if ((values.empty && !request.matchers?.hasMatchers()) || onlySizeAssertionsArePresent(values)) {
requestPattern.withRequestBody(WireMock.equalToJson(JsonOutput.toJson(getMatchingStrategy(request.body.clientValue).clientValue), false, false))
} else {
values.findAll{ !it.assertsSize() }.each {
@@ -114,12 +114,15 @@ class WireMockRequestStubStrategy extends BaseWireMockStubStrategy {
requestPattern.withRequestBody(convertToValuePattern(getMatchingStrategy(request.body.clientValue)))
}
}
private boolean onlySizeAssertionsArePresent(JsonPaths values) {
return !values.empty && !request.matchers?.hasMatchers() && values.every { it.assertsSize() }
}
private void appendMultipart(RequestPatternBuilder requestPattern) {
if (!request.multipart) {
return
}
if (request.multipart.clientValue instanceof Map) {
List<StringValuePattern> multipartPatterns = (request.multipart.clientValue as Map).collect {
(it.value instanceof NamedProperty

View File

@@ -16,13 +16,13 @@
package org.springframework.cloud.contract.verifier.util;
import static org.apache.commons.lang3.StringEscapeUtils.escapeJava;
import java.util.LinkedList;
import java.util.regex.Pattern;
import com.toomuchcoding.jsonassert.JsonVerifiable;
import static org.apache.commons.lang3.StringEscapeUtils.escapeJava;
/**
* Implementation of the {@link MethodBufferingJsonVerifiable} that contains a list
* of String method commands that need to be executed to assert JSONs.
@@ -187,6 +187,12 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
return readyToCheck;
}
@Override public MethodBufferingJsonVerifiable isEmpty() {
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.isEmpty(), this.methodsBuffer);
readyToCheck.methodsBuffer.offer(".isEmpty()");
return readyToCheck;
}
@Override
public MethodBufferingJsonVerifiable matches(String value) {
DelegatingJsonVerifiable readyToCheck = new FinishedDelegatingJsonVerifiable(this.delegate.matches(value), this.methodsBuffer);
@@ -228,7 +234,7 @@ class DelegatingJsonVerifiable implements MethodBufferingJsonVerifiable {
@Override
public boolean assertsSize() {
for (String s : this.methodsBuffer) {
if (s.contains(".hasSize(")) {
if (s.contains(".hasSize(") || s.contains(".isEmpty()")) {
return true;
}
}

View File

@@ -184,7 +184,7 @@ class JsonToJsonPathsConverter {
traverseRecursively(Object, valueToAsserter(key.arrayField(), ContentUtils.returnParsedObject(it)),
ContentUtils.returnParsedObject(it), closure)
}
} else if (value instanceof List) {
} else if (value instanceof List && !value.empty) {
MethodBufferingJsonVerifiable jsonPathVerifiable = createAsserterFromList(key, value)
addSizeVerificationForListWithPrimitives(key, closure, value)
value.each { def element ->
@@ -192,7 +192,9 @@ class JsonToJsonPathsConverter {
ContentUtils.returnParsedObject(element), closure)
}
return value
} else if (key.isIteratingOverArray()) {
} else if (value instanceof List && value.empty) {
return runClosure(closure, key, value)
} else if (key.isIteratingOverArray()) {
traverseRecursively(Object, key.arrayField().contains(ContentUtils.returnParsedObject(value)),
ContentUtils.returnParsedObject(value), closure)
}
@@ -292,6 +294,9 @@ class JsonToJsonPathsConverter {
}
private boolean listContainsOnlyPrimitives(List list) {
if (list.empty) {
return false
}
return list.every { def element ->
[String, Number, Boolean].any {
it.isAssignableFrom(element.getClass())
@@ -312,15 +317,22 @@ class JsonToJsonPathsConverter {
Object entrykey, value ->
def convertedValue = ContentUtils.returnParsedObject(value)
[entrykey, traverseRecursively(parentType,
convertedValue instanceof List ? listContainsOnlyPrimitives(convertedValue) ?
parentKey.arrayField(entrykey) :
parentKey.array(entrykey) :
convertedValue instanceof List ? list(convertedValue, entrykey, parentKey) :
convertedValue instanceof Map ? parentKey.field(new ShouldTraverse(entrykey)) :
valueToAsserter(parentKey.field(entrykey), convertedValue)
, convertedValue, closureToExecute)]
}
}
protected MethodBufferingJsonVerifiable list(List convertedValue, Object entrykey, MethodBufferingJsonVerifiable parentKey) {
if (convertedValue.empty) {
return parentKey.array(entrykey).isEmpty()
}
return listContainsOnlyPrimitives(convertedValue) ?
parentKey.arrayField(entrykey) :
parentKey.array(entrykey)
}
private void traverseRecursivelyForKey(def json, MethodBufferingJsonVerifiable rootKey, Closure closure) {
traverseRecursively(Map, rootKey, json, closure)
}

View File

@@ -59,6 +59,9 @@ public interface MethodBufferingJsonVerifiable
@Override
MethodBufferingJsonVerifiable isNull();
@Override
MethodBufferingJsonVerifiable isEmpty();
@Override
MethodBufferingJsonVerifiable matches(String value);

View File

@@ -2123,4 +2123,39 @@ World.'''"""
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | { Throwable t, OutputCapture capture -> t.message.contains("Cannot find matching method Script1#executedMethod") }
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } | { Throwable t, OutputCapture capture -> t.message.contains("Truncated class file") && capture.toString().contains("path(executedMethod())") }
}
@Issue('#203')
def "should create an assertion for an empty list for [#methodBuilderName]"() {
given:
Contract contractDsl = Contract.make {
request {
method 'GET'
url '/api/v1/xxxx'
}
response {
status 200
body([
status: '200',
list: [],
foo: ["bar", "baz"]
])
}
}
MethodBodyBuilder builder = methodBuilder(contractDsl)
BlockBuilder blockBuilder = new BlockBuilder(" ")
and:
builder.appendTo(blockBuilder)
String test = blockBuilder.toString()
when:
SyntaxChecker.tryToCompile(methodBuilderName, test)
then:
test.contains('assertThatJson(parsedJson).array("list").isEmpty()')
!test.contains('assertThatJson(parsedJson).array("foo").isEmpty()')
where:
methodBuilderName | methodBuilder
"MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) }
"MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) }
"JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) }
"JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) }
}
}