Merge branch '2.1.x'

This commit is contained in:
Marcin Grzejszczak
2019-11-06 15:45:41 +01:00
7 changed files with 139 additions and 11 deletions

View File

@@ -58,12 +58,8 @@ class GenericHttpBodyThen implements Then, BodyMethodVisitor {
endBodyBlock(this.blockBuilder);
this.blockBuilder.addEmptyLine();
startBodyBlock(this.blockBuilder, "and:");
Request request = metadata.getContract().getRequest();
this.thens.stream().filter(then -> then.accept(metadata))
.forEach(then -> then.apply(metadata));
String newBody = this.templateProcessor.transform(request,
this.blockBuilder.toString());
this.blockBuilder.updateContents(newBody);
return this;
}

View File

@@ -188,16 +188,19 @@ class JsonBodyVerificationBuilder implements BodyMethodGeneration, ClassVerifier
}
private String className(Object retrievedValue) {
return retrievedValue.getClass().getName().startsWith("java.lang") ?
retrievedValue.getClass().getSimpleName() : retrievedValue.getClass().getName();
return retrievedValue.getClass().getName().startsWith("java.lang")
? retrievedValue.getClass().getSimpleName()
: retrievedValue.getClass().getName();
}
private String objectToString(Object value) {
if (value instanceof Long) {
return String.valueOf(value).concat("L");
} else if (value instanceof Double) {
}
else if (value instanceof Double) {
return String.valueOf(value).concat("D");
} else if (value instanceof BigDecimal) {
}
else if (value instanceof BigDecimal) {
return quotedAndEscaped(value.toString());
}
return String.valueOf(value);

View File

@@ -0,0 +1,21 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.builder;
interface MethodPostProcessor extends MethodVisitor<MethodPostProcessor> {
}

View File

@@ -37,6 +37,8 @@ class SingleMethodBuilder {
private List<MethodMetadata> methodMetadata = new LinkedList<>();
private List<MethodPostProcessor> methodPostProcessors = new LinkedList<>();
private List<Given> givens = new LinkedList<>();
private List<When> whens = new LinkedList<>();
@@ -93,7 +95,9 @@ class SingleMethodBuilder {
.then(new JavaRestAssuredThen(this.blockBuilder,
this.generatedClassMetaData))
.then(new SpockRestAssuredThen(this.blockBuilder,
this.generatedClassMetaData));
this.generatedClassMetaData))
.methodPostProcessor(new TemplateUpdatingMethodPostProcessor(
this.blockBuilder));
}
SingleMethodBuilder jaxRs() {
@@ -101,7 +105,9 @@ class SingleMethodBuilder {
.when(new JavaJaxRsWhen(this.blockBuilder, this.generatedClassMetaData))
.when(new SpockJaxRsWhen(this.blockBuilder, this.generatedClassMetaData))
.then(new JavaJaxRsThen(this.blockBuilder, this.generatedClassMetaData))
.then(new SpockJaxRsThen(this.blockBuilder, this.generatedClassMetaData));
.then(new SpockJaxRsThen(this.blockBuilder, this.generatedClassMetaData))
.methodPostProcessor(
new TemplateUpdatingMethodPostProcessor(this.blockBuilder));
}
SingleMethodBuilder messaging() {
@@ -114,7 +120,8 @@ class SingleMethodBuilder {
.then(new SpockMessagingWithBodyThen(this.blockBuilder,
this.generatedClassMetaData))
.then(new SpockMessagingEmptyThen(this.blockBuilder,
this.generatedClassMetaData));
this.generatedClassMetaData))
.methodPostProcessor(new TemplateUpdatingMethodPostProcessor(this.blockBuilder));
// @formatter:on
}
@@ -133,6 +140,11 @@ class SingleMethodBuilder {
return this;
}
SingleMethodBuilder methodPostProcessor(MethodPostProcessor methodPostProcessor) {
this.methodPostProcessors.add(methodPostProcessor);
return this;
}
/**
* Mutates the {@link BlockBuilder} to generate a methodBuilder
* @return block builder with contents of a single methodBuilder
@@ -165,6 +177,10 @@ class SingleMethodBuilder {
visit(this.thens, metaData);
});
this.blockBuilder.addEmptyLine();
this.methodPostProcessors
.stream()
.filter(m -> m.accept(metaData))
.forEach(m -> m.apply(metaData));
// }
});
// @formatter:on

View File

@@ -0,0 +1,49 @@
/*
* Copyright 2013-2019 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.cloud.contract.verifier.builder;
import org.springframework.cloud.contract.spec.internal.Request;
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
import org.springframework.cloud.contract.verifier.template.HandlebarsTemplateProcessor;
import org.springframework.cloud.contract.verifier.template.TemplateProcessor;
class TemplateUpdatingMethodPostProcessor implements MethodPostProcessor {
private final BlockBuilder blockBuilder;
private final TemplateProcessor templateProcessor;
TemplateUpdatingMethodPostProcessor(BlockBuilder blockBuilder) {
this.blockBuilder = blockBuilder;
this.templateProcessor = new HandlebarsTemplateProcessor();
}
@Override
public MethodVisitor<MethodPostProcessor> apply(SingleContractMetadata metadata) {
Request request = metadata.getContract().getRequest();
String newBody = this.templateProcessor.transform(request,
this.blockBuilder.toString());
this.blockBuilder.updateContents(newBody);
return this;
}
@Override
public boolean accept(SingleContractMetadata metadata) {
return this.templateProcessor.containsTemplateEntry(this.blockBuilder.toString());
}
}

View File

@@ -29,6 +29,7 @@ import org.springframework.cloud.contract.spec.internal.DslProperty
import org.springframework.cloud.contract.spec.internal.Headers
import org.springframework.cloud.contract.verifier.util.ContentType
import org.springframework.cloud.contract.verifier.util.ContentUtils
import org.springframework.cloud.contract.verifier.util.MapConverter
import org.springframework.cloud.contract.verifier.util.NamesUtil
import org.springframework.util.Assert

View File

@@ -3012,4 +3012,46 @@ DocumentContext parsedJson = JsonPath.parse(json);
}
"webclient" | { properties.testMode = TestMode.WEBTESTCLIENT }
}
@Issue('#1163')
def 'should resolve from request evaluation even if there is no response body [#methodBuilderName]'() {
given:
Contract contractDsl = Contract.make {
request {
method PUT()
url '/frauds/name'
body([
name: $(anyAlphaUnicode())
])
headers {
contentType("application/json")
}
}
response {
status OK()
headers {
header(contentType(), "${fromRequest().header(contentType())}")
}
}
}
methodBuilder()
when:
String test = singleTestGenerator(contractDsl)
then:
SyntaxChecker.tryToCompile(methodBuilderName, test)
and:
!test.contains('''{{{request.headers.Content-Type.[0]}}}''')
where:
methodBuilderName | methodBuilder
"spock" | { properties.testFramework = TestFramework.SPOCK }
"testng" | { properties.testFramework = TestFramework.TESTNG }
"mockmvc" | { properties.testMode = TestMode.MOCKMVC }
"jaxrs-spock" | {
properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT
}
"jaxrs" | {
properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT
}
"webclient" | { properties.testMode = TestMode.WEBTESTCLIENT }
}
}