Refactored class and method generation (#1116)
following two event storming sessions with @pilloPl and @OlgaMaciaszek and the Spring Cloud Contract community we've decided to refactor the core modules of Spring Cloud Contract Verifier. The main idea is that the current `JavaTestGenerator`'s implementation no longer uses complex logic to generate classes and methods. We've introduced abstractions such as: - class body builder (to build classes) - groovy and java class metadata - imports (for various frameworks) - default setup for json, xml, restassured, jaxrs - class annotations for spock, junit and junit5 - field insertion e.g. for messaging
This commit is contained in:
committed by
GitHub
parent
954ddfb3d5
commit
972a50265f
@@ -1800,7 +1800,7 @@ following code listing shows the `SingleTestGenerator` interface:
|
||||
|
||||
[source,groovy]
|
||||
----
|
||||
include::{verifier_core_path}/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy[indent=0,lines=17..-1]
|
||||
include::{verifier_core_path}/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.java[indent=0,lines=17..-1]
|
||||
----
|
||||
|
||||
Again, you must provide a `spring.factories` file, such as the one shown in the following
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
|
||||
package org.springframework.cloud.contract.spec.internal
|
||||
|
||||
import java.util.function.Consumer
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.ToString
|
||||
import groovy.transform.TypeChecked
|
||||
@@ -48,6 +50,12 @@ class Cookies {
|
||||
}
|
||||
}
|
||||
|
||||
void executeForEachCookie(Consumer<Cookie> consumer) {
|
||||
entries?.each {
|
||||
cookie -> consumer.accept(cookie)
|
||||
}
|
||||
}
|
||||
|
||||
DslProperty matching(String value) {
|
||||
return new DslProperty(value)
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.contract.spec.internal
|
||||
|
||||
import java.util.function.Consumer
|
||||
import java.util.regex.Pattern
|
||||
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
@@ -23,7 +24,6 @@ import groovy.transform.ToString
|
||||
import groovy.transform.TypeChecked
|
||||
import groovy.transform.stc.ClosureParams
|
||||
import groovy.transform.stc.SimpleType
|
||||
|
||||
/**
|
||||
* Represents a set of headers of a request / response or a message
|
||||
*
|
||||
@@ -58,6 +58,12 @@ class Headers {
|
||||
}
|
||||
}
|
||||
|
||||
void executeForEachHeader(Consumer<Header> consumer) {
|
||||
entries?.each {
|
||||
header -> consumer.accept(header)
|
||||
}
|
||||
}
|
||||
|
||||
void headers(Set<Header> headers) {
|
||||
entries.addAll(headers)
|
||||
}
|
||||
|
||||
@@ -110,15 +110,24 @@ class RegexProperty extends DslProperty implements CanBeDynamic {
|
||||
}
|
||||
|
||||
Object generate() {
|
||||
String generatedValue = new Xeger(this.pattern.pattern()).generate()
|
||||
switch (this.clazz) {
|
||||
case Integer: return Integer.parseInt(generatedValue)
|
||||
case Double: return Double.parseDouble(generatedValue)
|
||||
case Float: return Float.parseFloat(generatedValue)
|
||||
case Long: return Long.parseLong(generatedValue)
|
||||
case Short: return Short.parseShort(generatedValue)
|
||||
case Boolean: return Boolean.parseBoolean(generatedValue)
|
||||
default: return generatedValue
|
||||
int retries = 3;
|
||||
try {
|
||||
String generatedValue = new Xeger(this.pattern.pattern()).generate()
|
||||
switch (this.clazz) {
|
||||
case Integer: return Integer.parseInt(generatedValue)
|
||||
case Double: return Double.parseDouble(generatedValue)
|
||||
case Float: return Float.parseFloat(generatedValue)
|
||||
case Long: return Long.parseLong(generatedValue)
|
||||
case Short: return Short.parseShort(generatedValue)
|
||||
case Boolean: return Boolean.parseBoolean(generatedValue)
|
||||
default: return generatedValue
|
||||
}
|
||||
} catch(NumberFormatException ex) {
|
||||
if (retries > 0) {
|
||||
retries = retries - 1
|
||||
return generate()
|
||||
}
|
||||
throw ex
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,16 @@ class RecursiveFilesConverterSpec extends Specification {
|
||||
def "on failure should break processing and throw meaningful exception"() {
|
||||
given:
|
||||
def sourceFile = tmpFolder.newFile("test.groovy")
|
||||
sourceFile.text = """\
|
||||
org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
method GET()
|
||||
url '/foo'
|
||||
}
|
||||
response {
|
||||
status OK()
|
||||
}
|
||||
}"""
|
||||
and:
|
||||
def stubGenerator = Stub(StubGenerator)
|
||||
stubGenerator.canHandleFileName(_) >> { true }
|
||||
|
||||
3
spring-cloud-contract-verifier/_request_request.json
Normal file
3
spring-cloud-contract-verifier/_request_request.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"status": "REQUEST"
|
||||
}
|
||||
BIN
spring-cloud-contract-verifier/_request_request.pdf
Normal file
BIN
spring-cloud-contract-verifier/_request_request.pdf
Normal file
Binary file not shown.
@@ -210,6 +210,25 @@
|
||||
<plugin>
|
||||
<groupId>org.codehaus.gmavenplus</groupId>
|
||||
<artifactId>gmavenplus-plugin</artifactId>
|
||||
<!-- Joint compilation -->
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>addSources</goal>
|
||||
<goal>addTestSources</goal>
|
||||
<goal>generateStubs</goal>
|
||||
<goal>compile</goal>
|
||||
<goal>generateTestStubs</goal>
|
||||
<goal>compileTests</goal>
|
||||
<goal>removeStubs</goal>
|
||||
<goal>removeTestStubs</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
|
||||
@@ -42,7 +42,6 @@ import static org.springframework.cloud.contract.verifier.util.NamesUtil.beforeL
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.convertIllegalPackageChars
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.directoryToPackage
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.toLastDot
|
||||
|
||||
/**
|
||||
* @author Jakub Kubrynski, codearte.io
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* 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 Acceptor {
|
||||
|
||||
boolean accept();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* 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 java.io.File;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties;
|
||||
import org.springframework.cloud.contract.verifier.util.NamesUtil;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
class BaseClassProvider {
|
||||
|
||||
private static final Log log = LogFactory.getLog(BaseClassProvider.class);
|
||||
|
||||
private static final String SEPARATOR = "_REPLACEME_";
|
||||
|
||||
String retrieveBaseClass(ContractVerifierConfigProperties properties,
|
||||
String includedDirectoryRelativePath) {
|
||||
String contractPathAsPackage = includedDirectoryRelativePath
|
||||
.replace(File.separator, ".");
|
||||
String contractPackage = includedDirectoryRelativePath.replace(File.separator,
|
||||
SEPARATOR);
|
||||
// package mapping takes super precedence
|
||||
if (properties.getBaseClassMappings() != null
|
||||
&& !properties.getBaseClassMappings().isEmpty()) {
|
||||
Optional<Map.Entry<String, String>> mapping = properties
|
||||
.getBaseClassMappings().entrySet().stream().filter(entry -> {
|
||||
String pattern = entry.getKey();
|
||||
return contractPathAsPackage.matches(pattern);
|
||||
}).findFirst();
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Matching pattern for contract package ["
|
||||
+ contractPathAsPackage + "] with setup "
|
||||
+ properties.getBaseClassMappings() + " is [" + mapping + "]");
|
||||
}
|
||||
if (mapping.isPresent()) {
|
||||
return mapping.get().getValue();
|
||||
}
|
||||
}
|
||||
if (StringUtils.isEmpty(properties.getPackageWithBaseClasses())) {
|
||||
return properties.getBaseClassForTests();
|
||||
}
|
||||
String generatedClassName = generateDefaultBaseClassName(contractPackage,
|
||||
properties);
|
||||
return generatedClassName + "Base";
|
||||
}
|
||||
|
||||
private String generateDefaultBaseClassName(String classPackage,
|
||||
ContractVerifierConfigProperties properties) {
|
||||
String[] splitPackage = NamesUtil.convertIllegalPackageChars(classPackage)
|
||||
.split(SEPARATOR);
|
||||
if (splitPackage.length > 1) {
|
||||
String last = NamesUtil.capitalize(splitPackage[splitPackage.length - 1]);
|
||||
String butLast = NamesUtil.capitalize(splitPackage[splitPackage.length - 2]);
|
||||
return properties.getPackageWithBaseClasses() + "." + butLast + last;
|
||||
}
|
||||
return properties.getPackageWithBaseClasses() + "."
|
||||
+ NamesUtil.capitalize(splitPackage[0]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
package org.springframework.cloud.contract.verifier.builder
|
||||
|
||||
import groovy.transform.CompileDynamic
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
|
||||
@@ -33,6 +33,8 @@ class BlockBuilder {
|
||||
private final StringBuilder builder
|
||||
private final String spacer
|
||||
private int indents
|
||||
private String lineEnding = ""
|
||||
private String labelPrefix = ""
|
||||
|
||||
/**
|
||||
* @param spacer - char used for spacing
|
||||
@@ -42,6 +44,34 @@ class BlockBuilder {
|
||||
builder = new StringBuilder()
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup line ending
|
||||
*/
|
||||
BlockBuilder setupLineEnding(String lineEnding) {
|
||||
this.lineEnding = lineEnding
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Setup label prefix
|
||||
*/
|
||||
BlockBuilder setupLabelPrefix(String labelPrefix) {
|
||||
this.labelPrefix = labelPrefix
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
String getLineEnding() {
|
||||
return this.lineEnding
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds indents to start a new block
|
||||
*/
|
||||
BlockBuilder appendWithLabelPrefix(String label) {
|
||||
return append(this.labelPrefix).append(label)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds indents to start a new block
|
||||
*/
|
||||
@@ -75,8 +105,27 @@ class BlockBuilder {
|
||||
}
|
||||
|
||||
BlockBuilder addLine(String line) {
|
||||
return addIndented(line).append("\n")
|
||||
}
|
||||
|
||||
BlockBuilder addIndented(String line) {
|
||||
return addIndentation().append(line)
|
||||
}
|
||||
|
||||
BlockBuilder addIndented(Runnable runnable) {
|
||||
addIndentation()
|
||||
builder << "$line\n"
|
||||
runnable.run()
|
||||
return this
|
||||
}
|
||||
|
||||
BlockBuilder addLineWithEnding(String line) {
|
||||
addIndentation()
|
||||
append(line).addEndingIfNotPresent().addEmptyLine()
|
||||
return this
|
||||
}
|
||||
|
||||
BlockBuilder addEndingIfNotPresent() {
|
||||
addAtTheEnd(lineEnding)
|
||||
return this
|
||||
}
|
||||
|
||||
@@ -85,22 +134,49 @@ class BlockBuilder {
|
||||
return this
|
||||
}
|
||||
|
||||
@CompileDynamic
|
||||
private void addIndentation() {
|
||||
BlockBuilder appendWithSpace(String text) {
|
||||
return addAtTheEnd(" ").append(text)
|
||||
}
|
||||
|
||||
BlockBuilder appendWithSpace(Runnable runnable) {
|
||||
addAtTheEnd(" ")
|
||||
runnable.run()
|
||||
return this
|
||||
}
|
||||
|
||||
// synactic sugar
|
||||
BlockBuilder append(Runnable runnable) {
|
||||
runnable.run()
|
||||
return this
|
||||
}
|
||||
|
||||
BlockBuilder append(String string) {
|
||||
builder << string
|
||||
return this
|
||||
}
|
||||
|
||||
BlockBuilder addIndentation() {
|
||||
indents.times {
|
||||
builder << spacer
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
@PackageScope
|
||||
BlockBuilder addBlock(MethodBuilder methodBuilder) {
|
||||
BlockBuilder inBraces(Runnable runnable) {
|
||||
builder.append("{\n")
|
||||
startBlock()
|
||||
methodBuilder.appendTo(this)
|
||||
runnable.run()
|
||||
endBlock()
|
||||
addEmptyLine()
|
||||
addAtTheEnd('\n')
|
||||
addLine("}")
|
||||
return this
|
||||
}
|
||||
|
||||
boolean endsWith(String text) {
|
||||
return builder.toString().endsWith(text)
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the given text at the end of the line
|
||||
*
|
||||
@@ -110,10 +186,23 @@ class BlockBuilder {
|
||||
String lastChar = builder.charAt(builder.length() - 1) as String
|
||||
String secondLastChar = builder.length() >= 2 ? builder.
|
||||
charAt(builder.length() - 2) as String : ""
|
||||
if (endsWithNewLine(lastChar) && aSpecialSign(secondLastChar, toAdd)) {
|
||||
boolean isEndWithNewLine = endsWithNewLine(lastChar)
|
||||
boolean lastCharSpecial = aSpecialSign(lastChar, toAdd)
|
||||
boolean secondLastCharSpecial = aSpecialSign(secondLastChar, toAdd)
|
||||
boolean lineEndingToAdd = toAdd == lineEnding
|
||||
// lastChar = [;] , toAdd = [;]
|
||||
if (lastChar == toAdd) {
|
||||
return this
|
||||
}
|
||||
else if (endsWithNewLine(lastChar) && !aSpecialSign(secondLastChar, toAdd)) {
|
||||
// secondLastChar = [ ], lastChar = [{] , toAdd = [;]
|
||||
else if ((!isEndWithNewLine && lastCharSpecial) && lineEndingToAdd) {
|
||||
return this
|
||||
}
|
||||
// secondLastChar = [{], lastChar = [\n] , toAdd = [;]
|
||||
else if (isEndWithNewLine && secondLastCharSpecial) {
|
||||
return this
|
||||
}
|
||||
else if (isEndWithNewLine && !secondLastCharSpecial) {
|
||||
builder.replace(builder.length() - 1, builder.length(), toAdd)
|
||||
builder << '\n'
|
||||
}
|
||||
@@ -131,7 +220,12 @@ class BlockBuilder {
|
||||
if (!character) {
|
||||
return false
|
||||
}
|
||||
return character == "{" || character == toAdd
|
||||
return character == "{" ||
|
||||
(character == spacer && toAdd == spacer) ||
|
||||
(character == spacer && toAdd == " ") ||
|
||||
character == toAdd ||
|
||||
(endsWithNewLine(character) &&
|
||||
(toAdd == '\n' || toAdd == " " || toAdd == lineEnding))
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,130 @@
|
||||
/*
|
||||
* 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 java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty;
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty;
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class BodyAssertionLineCreator {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final BodyReader bodyReader;
|
||||
|
||||
private final String byteArrayString;
|
||||
|
||||
private final ComparisonBuilder comparisonBuilder;
|
||||
|
||||
BodyAssertionLineCreator(BlockBuilder blockBuilder, GeneratedClassMetaData metaData,
|
||||
String byteArrayString, ComparisonBuilder comparisonBuilder) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.bodyReader = new BodyReader(metaData);
|
||||
this.byteArrayString = byteArrayString;
|
||||
this.comparisonBuilder = comparisonBuilder;
|
||||
}
|
||||
|
||||
void appendBodyAssertionLine(SingleContractMetadata metadata, String property,
|
||||
Object value) {
|
||||
if (value instanceof String && ((String) value).startsWith("$")) {
|
||||
String newValue = stripFirstChar((String) value).replaceAll("\\$value",
|
||||
"responseBody" + property);
|
||||
this.blockBuilder.addLineWithEnding(newValue);
|
||||
}
|
||||
else {
|
||||
this.blockBuilder.addLineWithEnding(
|
||||
getResponseBodyPropertyComparisonString(metadata, property, value));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the code that for the given {@code property} will compare it to the given
|
||||
* Object {@code value}
|
||||
*/
|
||||
private String getResponseBodyPropertyComparisonString(
|
||||
SingleContractMetadata singleContractMetadata, String property,
|
||||
Object value) {
|
||||
if (value instanceof FromFileProperty) {
|
||||
return getResponseBodyPropertyComparisonString(singleContractMetadata,
|
||||
property, (FromFileProperty) value);
|
||||
}
|
||||
else if (value instanceof Pattern) {
|
||||
return getResponseBodyPropertyComparisonString(property, (Pattern) value);
|
||||
}
|
||||
else if (value instanceof ExecutionProperty) {
|
||||
return getResponseBodyPropertyComparisonString(property,
|
||||
(ExecutionProperty) value);
|
||||
}
|
||||
else if (value instanceof DslProperty) {
|
||||
return getResponseBodyPropertyComparisonString(singleContractMetadata,
|
||||
property, ((DslProperty) value).getServerValue());
|
||||
}
|
||||
return getResponseBodyPropertyComparisonString(property, value.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the code that for the given {@code property} will compare it to the given
|
||||
* byte[] {@code value}
|
||||
*/
|
||||
private String getResponseBodyPropertyComparisonString(
|
||||
SingleContractMetadata singleContractMetadata, String property,
|
||||
FromFileProperty value) {
|
||||
if (value.isByte()) {
|
||||
return this.comparisonBuilder.assertThat(this.byteArrayString)
|
||||
+ this.comparisonBuilder.isEqualToUnquoted(this.bodyReader
|
||||
.readBytesFromFileString(singleContractMetadata, value,
|
||||
CommunicationType.RESPONSE));
|
||||
}
|
||||
return getResponseBodyPropertyComparisonString(property, value.asString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the code that for the given {@code property} will compare it to the given
|
||||
* String {@code value}
|
||||
*/
|
||||
private String getResponseBodyPropertyComparisonString(String property,
|
||||
String value) {
|
||||
return this.comparisonBuilder.assertThatUnescaped("responseBody" + property,
|
||||
value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the code that for the given {@code property} will match it to the given
|
||||
* regular expression {@code value}
|
||||
*/
|
||||
private String getResponseBodyPropertyComparisonString(String property,
|
||||
Pattern value) {
|
||||
return this.comparisonBuilder.assertThat("responseBody" + property, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the code that for the given {@code property} will match it to the given
|
||||
* {@link ExecutionProperty} value
|
||||
*/
|
||||
private String getResponseBodyPropertyComparisonString(String property,
|
||||
ExecutionProperty value) {
|
||||
return value.insertValue("responseBody" + property);
|
||||
}
|
||||
|
||||
private String stripFirstChar(String s) {
|
||||
return s.substring(1);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
/*
|
||||
* 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.apache.commons.text.StringEscapeUtils
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.BodyMatcher
|
||||
import org.springframework.cloud.contract.spec.internal.MatchingType
|
||||
import org.springframework.util.SerializationUtils
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.1.0
|
||||
*/
|
||||
trait BodyMethodGeneration {
|
||||
|
||||
// Doing a clone doesn't work for nested lists...
|
||||
Object cloneBody(Object object) {
|
||||
if (object instanceof List || object instanceof Map) {
|
||||
byte[] serializedObject = SerializationUtils.serialize(object)
|
||||
return SerializationUtils.deserialize(serializedObject)
|
||||
}
|
||||
try {
|
||||
return object.clone()
|
||||
}
|
||||
catch (CloneNotSupportedException ignored) {
|
||||
return object
|
||||
}
|
||||
}
|
||||
|
||||
void addColonIfRequired(Optional<String> lineSuffix, BlockBuilder blockBuilder) {
|
||||
lineSuffix.ifPresent({
|
||||
blockBuilder.addAtTheEnd(lineSuffix.get())
|
||||
})
|
||||
}
|
||||
|
||||
void addBodyMatchingBlock(List<BodyMatcher> matchers, BlockBuilder blockBuilder,
|
||||
Object responseBody, boolean shouldCommentOutBDDBlocks) {
|
||||
blockBuilder.endBlock()
|
||||
blockBuilder.addLine(getAssertionJoiner(shouldCommentOutBDDBlocks))
|
||||
blockBuilder.startBlock()
|
||||
matchers.each {
|
||||
if (it.matchingType() == MatchingType.NULL) {
|
||||
methodForNullCheck(it, blockBuilder)
|
||||
}
|
||||
else if (MatchingType.regexRelated(it.matchingType())
|
||||
|| it
|
||||
.matchingType()
|
||||
== MatchingType.EQUALITY) {
|
||||
methodForEqualityCheck(it, blockBuilder, responseBody)
|
||||
}
|
||||
else if (it.matchingType() == MatchingType.COMMAND) {
|
||||
methodForCommandExecution(it, blockBuilder, responseBody)
|
||||
}
|
||||
else {
|
||||
methodForTypeCheck(it, blockBuilder, responseBody)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
String quotedAndEscaped(String string) {
|
||||
return '"' + StringEscapeUtils.escapeJava(string) + '"'
|
||||
}
|
||||
|
||||
abstract void methodForNullCheck(BodyMatcher bodyMatcher, BlockBuilder bb)
|
||||
|
||||
abstract void methodForEqualityCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object body)
|
||||
|
||||
abstract void methodForCommandExecution(BodyMatcher bodyMatcher, BlockBuilder bb, Object body)
|
||||
|
||||
abstract void methodForTypeCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object body)
|
||||
|
||||
String getAssertionJoiner(boolean shouldCommentOutBDDBlocks) {
|
||||
return shouldCommentOutBDDBlocks ? '// and:' : 'and:'
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.BodyMatcher;
|
||||
import org.springframework.cloud.contract.spec.internal.MatchingType;
|
||||
import org.springframework.util.SerializationUtils;
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.1.0
|
||||
*/
|
||||
interface BodyMethodGeneration {
|
||||
|
||||
default Object cloneBody(Object object) {
|
||||
byte[] serializedObject = SerializationUtils.serialize(object);
|
||||
return SerializationUtils.deserialize(serializedObject);
|
||||
}
|
||||
|
||||
default void addColonIfRequired(Optional<String> lineSuffix,
|
||||
BlockBuilder blockBuilder) {
|
||||
lineSuffix.ifPresent(s -> blockBuilder.addAtTheEnd(lineSuffix.get()));
|
||||
}
|
||||
|
||||
default void addBodyMatchingBlock(List<BodyMatcher> matchers,
|
||||
BlockBuilder blockBuilder, Object responseBody,
|
||||
boolean shouldCommentOutBDDBlocks) {
|
||||
blockBuilder.endBlock();
|
||||
blockBuilder.addLine(getAssertionJoiner(shouldCommentOutBDDBlocks));
|
||||
blockBuilder.startBlock();
|
||||
matchers.forEach(it -> {
|
||||
if (it.matchingType() == MatchingType.NULL) {
|
||||
methodForNullCheck(it, blockBuilder);
|
||||
}
|
||||
else if (MatchingType.regexRelated(it.matchingType())
|
||||
|| it.matchingType() == MatchingType.EQUALITY) {
|
||||
methodForEqualityCheck(it, blockBuilder, responseBody);
|
||||
}
|
||||
else if (it.matchingType() == MatchingType.COMMAND) {
|
||||
methodForCommandExecution(it, blockBuilder, responseBody);
|
||||
}
|
||||
else {
|
||||
methodForTypeCheck(it, blockBuilder, responseBody);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
default String quotedAndEscaped(String string) {
|
||||
return '"' + StringEscapeUtils.escapeJava(string) + '"';
|
||||
}
|
||||
|
||||
void methodForNullCheck(BodyMatcher bodyMatcher, BlockBuilder bb);
|
||||
|
||||
void methodForEqualityCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object body);
|
||||
|
||||
void methodForCommandExecution(BodyMatcher bodyMatcher, BlockBuilder bb, Object body);
|
||||
|
||||
void methodForTypeCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object body);
|
||||
|
||||
default String getAssertionJoiner(boolean shouldCommentOutBDDBlocks) {
|
||||
return shouldCommentOutBDDBlocks ? "// and:" : "and:";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,142 @@
|
||||
/*
|
||||
* 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 java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
/**
|
||||
* Adds a label, proper indents and line endings for the body of a method.
|
||||
*/
|
||||
interface BodyMethodVisitor {
|
||||
|
||||
/**
|
||||
* Adds a starting body method block. E.g. //given: together with all indents
|
||||
* @param blockBuilder
|
||||
* @param label
|
||||
* @return
|
||||
*/
|
||||
default BlockBuilder startBodyBlock(BlockBuilder blockBuilder, String label) {
|
||||
return blockBuilder.addIndentation().appendWithLabelPrefix(label).addEmptyLine()
|
||||
.startBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks matching elements, visits them and applies indents.
|
||||
* @param blockBuilder
|
||||
* @param methodVisitors
|
||||
* @param singleContractMetadata
|
||||
*/
|
||||
default void indentedBodyBlock(BlockBuilder blockBuilder,
|
||||
List<? extends MethodVisitor> methodVisitors,
|
||||
SingleContractMetadata singleContractMetadata) {
|
||||
List<MethodVisitor> visitors = filterVisitors(methodVisitors,
|
||||
singleContractMetadata);
|
||||
if (visitors.isEmpty()) {
|
||||
blockBuilder.addEndingIfNotPresent().addEmptyLine();
|
||||
blockBuilder.endBlock();
|
||||
return;
|
||||
}
|
||||
blockBuilder.addEmptyLine().indent();
|
||||
applyVisitors(blockBuilder, singleContractMetadata, visitors);
|
||||
endIndentedBodyBlock(blockBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks matching visitors.
|
||||
* @param methodVisitors
|
||||
* @param singleContractMetadata
|
||||
* @return
|
||||
*/
|
||||
default List<MethodVisitor> filterVisitors(
|
||||
List<? extends MethodVisitor> methodVisitors,
|
||||
SingleContractMetadata singleContractMetadata) {
|
||||
return methodVisitors.stream()
|
||||
.filter(given -> given.accept(singleContractMetadata))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/**
|
||||
* Picks matching elements, visits them. Doesn't apply indents. Useful for the //
|
||||
* then: block where there is no method chaining.
|
||||
* @param blockBuilder
|
||||
* @param methodVisitors
|
||||
* @param singleContractMetadata
|
||||
*/
|
||||
default void bodyBlock(BlockBuilder blockBuilder,
|
||||
List<? extends MethodVisitor> methodVisitors,
|
||||
SingleContractMetadata singleContractMetadata) {
|
||||
List<MethodVisitor> visitors = filterVisitors(methodVisitors,
|
||||
singleContractMetadata);
|
||||
if (visitors.isEmpty()) {
|
||||
blockBuilder.addEndingIfNotPresent().addEmptyLine();
|
||||
return;
|
||||
}
|
||||
applyVisitorsWithEnding(blockBuilder, singleContractMetadata, visitors);
|
||||
endBodyBlock(blockBuilder);
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes logic for all the matching visitors.
|
||||
* @param blockBuilder
|
||||
* @param singleContractMetadata
|
||||
* @param visitors
|
||||
*/
|
||||
default void applyVisitors(BlockBuilder blockBuilder,
|
||||
SingleContractMetadata singleContractMetadata, List<MethodVisitor> visitors) {
|
||||
Iterator<MethodVisitor> iterator = visitors.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
MethodVisitor visitor = iterator.next();
|
||||
visitor.apply(singleContractMetadata);
|
||||
if (iterator.hasNext()) {
|
||||
blockBuilder.addEmptyLine();
|
||||
}
|
||||
}
|
||||
blockBuilder.addEndingIfNotPresent();
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes logic for all the matching visitors.
|
||||
* @param blockBuilder
|
||||
* @param singleContractMetadata
|
||||
* @param visitors
|
||||
*/
|
||||
default void applyVisitorsWithEnding(BlockBuilder blockBuilder,
|
||||
SingleContractMetadata singleContractMetadata, List<MethodVisitor> visitors) {
|
||||
Iterator<MethodVisitor> iterator = visitors.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
MethodVisitor visitor = iterator.next();
|
||||
visitor.apply(singleContractMetadata);
|
||||
blockBuilder.addEndingIfNotPresent();
|
||||
if (iterator.hasNext()) {
|
||||
blockBuilder.addEmptyLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default void endIndentedBodyBlock(BlockBuilder blockBuilder) {
|
||||
blockBuilder.addEndingIfNotPresent().unindent().endBlock();
|
||||
}
|
||||
|
||||
default void endBodyBlock(BlockBuilder blockBuilder) {
|
||||
blockBuilder.addEndingIfNotPresent().endBlock();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,164 @@
|
||||
/*
|
||||
* 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 java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import groovy.json.JsonOutput;
|
||||
import groovy.lang.Closure;
|
||||
import groovy.lang.GString;
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty;
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
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 static org.apache.commons.text.StringEscapeUtils.escapeJava;
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.DEFINED;
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.FORM;
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.JSON;
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.TEXT;
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentUtils.extractValue;
|
||||
|
||||
interface BodyParser extends BodyThen {
|
||||
|
||||
String byteArrayString();
|
||||
|
||||
default String convertUnicodeEscapesIfRequired(String json) {
|
||||
String unescapedJson = StringEscapeUtils.unescapeEcmaScript(json);
|
||||
return escapeJava(unescapedJson);
|
||||
}
|
||||
|
||||
default String convertToJsonString(Object bodyValue) {
|
||||
String json = JsonOutput.toJson(bodyValue);
|
||||
json = convertUnicodeEscapesIfRequired(json);
|
||||
return trimRepeatedQuotes(json);
|
||||
}
|
||||
|
||||
default String trimRepeatedQuotes(String toTrim) {
|
||||
if (toTrim.startsWith("\"")) {
|
||||
return toTrim.replaceAll("\"", "");
|
||||
// #261
|
||||
}
|
||||
else if (toTrim.startsWith("\\\"") && toTrim.endsWith("\\\"")) {
|
||||
return toTrim.substring(2, toTrim.length() - 2);
|
||||
}
|
||||
return toTrim;
|
||||
}
|
||||
|
||||
default Object convertResponseBody(SingleContractMetadata metadata) {
|
||||
ContentType contentType = metadata.getOutputTestContentType();
|
||||
DslProperty body = responseBody(metadata);
|
||||
Object responseBody = extractServerValueFromBody(contentType,
|
||||
body.getServerValue());
|
||||
if (responseBody instanceof FromFileProperty) {
|
||||
responseBody = ((FromFileProperty) responseBody).asString();
|
||||
}
|
||||
else if (responseBody instanceof GString) {
|
||||
responseBody = extractValue((GString) responseBody, contentType,
|
||||
o -> o instanceof DslProperty ? ((DslProperty) o).getServerValue()
|
||||
: o);
|
||||
}
|
||||
else if (responseBody instanceof DslProperty) {
|
||||
responseBody = MapConverter.getTestSideValues(responseBody);
|
||||
}
|
||||
return responseBody;
|
||||
}
|
||||
|
||||
String responseAsString();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
default String requestBodyAsString(SingleContractMetadata metadata) {
|
||||
ContentType contentType = metadata.getInputTestContentType();
|
||||
DslProperty body = requestBody(metadata);
|
||||
Object bodyValue = extractServerValueFromBody(contentType, body.getServerValue());
|
||||
if (contentType == ContentType.FORM) {
|
||||
if (bodyValue instanceof Map) {
|
||||
// [a:3, b:4] == "a=3&b=4"
|
||||
return ((Map) bodyValue).entrySet().stream().map(o -> {
|
||||
Map.Entry entry = (Map.Entry) o;
|
||||
return convertUnicodeEscapesIfRequired(entry.getKey().toString() + "="
|
||||
+ MapConverter.getTestSideValuesForText(entry.getValue()));
|
||||
}).collect(Collectors.joining("&")).toString();
|
||||
}
|
||||
else if (bodyValue instanceof List) {
|
||||
// ["a=3", "b=4"] == "a=3&b=4"
|
||||
return ((List) bodyValue).stream()
|
||||
.map(o -> convertUnicodeEscapesIfRequired(
|
||||
MapConverter.getTestSideValuesForText(o).toString()))
|
||||
.collect(Collectors.joining("&")).toString();
|
||||
}
|
||||
}
|
||||
else {
|
||||
return convertToJsonString(bodyValue);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the passed body into ints server side representation. All
|
||||
* {@link DslProperty} will return their server side values
|
||||
*/
|
||||
default Object extractServerValueFromBody(ContentType contentType, Object bodyValue) {
|
||||
if (bodyValue instanceof GString) {
|
||||
return extractValue((GString) bodyValue, contentType,
|
||||
ContentUtils.GET_TEST_SIDE);
|
||||
}
|
||||
if (TEXT != contentType && FORM != contentType && DEFINED != contentType) {
|
||||
boolean dontParseStrings = contentType == JSON && bodyValue instanceof Map;
|
||||
Closure parsingClosure = dontParseStrings ? Closure.IDENTITY
|
||||
: MapConverter.JSON_PARSING_CLOSURE;
|
||||
return MapConverter.transformValues(bodyValue, ContentUtils.GET_TEST_SIDE,
|
||||
parsingClosure);
|
||||
}
|
||||
return bodyValue;
|
||||
}
|
||||
|
||||
default String escape(String text) {
|
||||
return StringEscapeUtils.escapeJava(text);
|
||||
}
|
||||
|
||||
default String escapeForSimpleTextAssertion(String text) {
|
||||
return text;
|
||||
}
|
||||
|
||||
default String postProcessJsonPath(String jsonPath) {
|
||||
return jsonPath;
|
||||
}
|
||||
|
||||
default String quotedLongText(Object text) {
|
||||
return quotedEscapedLongText(escape(text.toString()));
|
||||
}
|
||||
|
||||
default String quotedEscapedLongText(Object text) {
|
||||
return "\"" + text.toString() + "\"";
|
||||
}
|
||||
|
||||
default String quotedShortText(Object text) {
|
||||
return quotedLongText(text);
|
||||
}
|
||||
|
||||
default String quotedEscapedShortText(Object text) {
|
||||
return quotedEscapedLongText(text);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* 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 java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
class BodyReader {
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
BodyReader(GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
String readBytesFromFileString(SingleContractMetadata metadata,
|
||||
FromFileProperty property, CommunicationType side) {
|
||||
String fileName = byteBodyToAFileForTestMethod(metadata, property, side);
|
||||
return "fileToBytes(this, \"" + fileName + "\")";
|
||||
}
|
||||
|
||||
String readStringFromFileString(SingleContractMetadata metadata,
|
||||
FromFileProperty property, CommunicationType side) {
|
||||
return "new String(" + readBytesFromFileString(metadata, property, side) + ")";
|
||||
}
|
||||
|
||||
private String byteBodyToAFileForTestMethod(SingleContractMetadata metadata,
|
||||
FromFileProperty property, CommunicationType side) {
|
||||
GeneratedClassDataForMethod classDataForMethod = new GeneratedClassDataForMethod(
|
||||
this.generatedClassMetaData.generatedClassData, metadata.methodName());
|
||||
String newFileName = classDataForMethod.getMethodName() + "_"
|
||||
+ side.name().toLowerCase() + "_" + property.fileName();
|
||||
java.nio.file.Path parent = classDataForMethod.testClassPath().getParent();
|
||||
if (parent == null) {
|
||||
parent = classDataForMethod.testClassPath();
|
||||
}
|
||||
File newFile = new File(parent.toFile(), newFileName);
|
||||
// for IDE
|
||||
try {
|
||||
Files.write(newFile.toPath(), property.asBytes());
|
||||
// for plugin
|
||||
generatedTestResourcesFileBytes(property, newFile);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
return newFileName;
|
||||
}
|
||||
|
||||
private void generatedTestResourcesFileBytes(FromFileProperty property, File newFile)
|
||||
throws IOException {
|
||||
Assert.notNull(
|
||||
this.generatedClassMetaData.configProperties.getGeneratedTestSourcesDir(),
|
||||
"No generated test sources directory set");
|
||||
Assert.notNull(
|
||||
this.generatedClassMetaData.configProperties
|
||||
.getGeneratedTestResourcesDir(),
|
||||
"No generated test resources directory set");
|
||||
Path path = this.generatedClassMetaData.configProperties
|
||||
.getGeneratedTestSourcesDir().toPath();
|
||||
Path relativePath = path.relativize(newFile.toPath());
|
||||
File newFileInGeneratedTestSources = new File(
|
||||
this.generatedClassMetaData.configProperties
|
||||
.getGeneratedTestResourcesDir(),
|
||||
relativePath.toString());
|
||||
newFileInGeneratedTestSources.getParentFile().mkdirs();
|
||||
Files.write(newFileInGeneratedTestSources.toPath(), property.asBytes());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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.BodyMatchers;
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
interface BodyThen {
|
||||
|
||||
default DslProperty requestBody(SingleContractMetadata metadata) {
|
||||
return metadata.getContract().getRequest().getBody();
|
||||
}
|
||||
|
||||
default DslProperty responseBody(SingleContractMetadata metadata) {
|
||||
return metadata.getContract().getResponse().getBody();
|
||||
}
|
||||
|
||||
default BodyMatchers responseBodyMatchers(SingleContractMetadata metadata) {
|
||||
return metadata.getContract().getResponse().getBodyMatchers();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 ClassAnnotation extends Visitor<ClassAnnotation> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
class ClassAnnotationsBuilder {
|
||||
|
||||
private final GeneratedTestClassBuilder parentBuilder;
|
||||
|
||||
private final BlockBuilder builder;
|
||||
|
||||
private final GeneratedClassMetaData metaData;
|
||||
|
||||
ClassAnnotationsBuilder(GeneratedTestClassBuilder generatedTestClassBuilder) {
|
||||
this.parentBuilder = generatedTestClassBuilder;
|
||||
this.builder = generatedTestClassBuilder.blockBuilder;
|
||||
this.metaData = generatedTestClassBuilder.generatedClassMetaData;
|
||||
}
|
||||
|
||||
ClassAnnotationsBuilder jUnit4() {
|
||||
this.parentBuilder
|
||||
.classAnnotations(new JUnit4OrderClassAnnotation(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
ClassAnnotationsBuilder jUnit5() {
|
||||
this.parentBuilder
|
||||
.classAnnotations(new JUnit5OrderClassAnnotation(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
ClassAnnotationsBuilder spock() {
|
||||
this.parentBuilder
|
||||
.classAnnotations(new SpockOrderClassAnnotation(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder build() {
|
||||
return this.parentBuilder;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* 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 java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Builds the body of the class. Sets fields, methods.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 2.2.0
|
||||
*/
|
||||
class ClassBodyBuilder {
|
||||
|
||||
private List<Field> fields = new LinkedList<>();
|
||||
|
||||
private SingleMethodBuilder methodBuilder;
|
||||
|
||||
final BlockBuilder blockBuilder;
|
||||
|
||||
final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private ClassBodyBuilder(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
static ClassBodyBuilder builder(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
return new ClassBodyBuilder(blockBuilder, generatedClassMetaData);
|
||||
}
|
||||
|
||||
FieldBuilder field() {
|
||||
return new FieldBuilder(this);
|
||||
}
|
||||
|
||||
ClassBodyBuilder field(Field field) {
|
||||
this.fields.add(field);
|
||||
return this;
|
||||
}
|
||||
|
||||
ClassBodyBuilder methodBuilder(SingleMethodBuilder methodBuilder) {
|
||||
this.methodBuilder = methodBuilder;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Mutates the {@link BlockBuilder} to generate methods and fields.
|
||||
* @return block builder with contents of built methods
|
||||
*/
|
||||
BlockBuilder build() {
|
||||
this.blockBuilder.inBraces(() -> {
|
||||
// @Rule ...
|
||||
visit(this.fields);
|
||||
// new line if fields added
|
||||
this.methodBuilder.build();
|
||||
});
|
||||
return this.blockBuilder;
|
||||
}
|
||||
|
||||
void visit(List<? extends Visitor> list) {
|
||||
List<? extends Visitor> visitors = list.stream().filter(Acceptor::accept)
|
||||
.collect(Collectors.toList());
|
||||
Iterator<? extends Visitor> iterator = visitors.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Visitor visitor = iterator.next();
|
||||
visitor.call();
|
||||
this.blockBuilder.addEndingIfNotPresent();
|
||||
if (iterator.hasNext()) {
|
||||
this.blockBuilder.addEmptyLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,232 +0,0 @@
|
||||
/*
|
||||
* 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 groovy.transform.CompileStatic
|
||||
import groovy.transform.PackageScope
|
||||
import org.apache.commons.logging.Log
|
||||
import org.apache.commons.logging.LogFactory
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework
|
||||
import org.springframework.cloud.contract.verifier.util.NamesUtil
|
||||
|
||||
/**
|
||||
* Builds a class. Adds all the imports, static imports etc.
|
||||
*
|
||||
* @author Jakub Kubrynski, codearte.io
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@CompileStatic
|
||||
@PackageScope
|
||||
class ClassBuilder {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ClassBuilder)
|
||||
|
||||
private static final String SEPARATOR = "_REPLACEME_"
|
||||
|
||||
private final String className
|
||||
private final String packageName
|
||||
private final String baseClass
|
||||
private final List<String> imports = []
|
||||
private final List<String> staticImports = []
|
||||
private final List<String> rules = []
|
||||
private final List<String> fields = []
|
||||
private final List<MethodBuilder> methods = []
|
||||
private final List<String> classLevelAnnotations = []
|
||||
private final TestFramework lang
|
||||
|
||||
private ClassBuilder(String className, String packageName, String baseClass, TestFramework lang) {
|
||||
this.lang = lang
|
||||
if (baseClass) {
|
||||
imports << baseClass
|
||||
}
|
||||
this.baseClass = NamesUtil.afterLastDot(baseClass)
|
||||
this.packageName = packageName
|
||||
this.className = className
|
||||
}
|
||||
|
||||
/**
|
||||
* @return a{@link ClassBuilder} for the given parameters
|
||||
*/
|
||||
static ClassBuilder createClass(String className, String classPackage, ContractVerifierConfigProperties properties,
|
||||
String includedDirectoryRelativePath) {
|
||||
String baseClassForTests
|
||||
if (properties.testFramework == TestFramework.SPOCK && !properties.baseClassForTests
|
||||
&& !properties.packageWithBaseClasses
|
||||
&& !properties.baseClassMappings) {
|
||||
baseClassForTests = 'spock.lang.Specification'
|
||||
}
|
||||
else {
|
||||
baseClassForTests =
|
||||
retrieveBaseClass(properties, includedDirectoryRelativePath)
|
||||
}
|
||||
return new ClassBuilder(className, classPackage, baseClassForTests, properties.testFramework)
|
||||
}
|
||||
|
||||
protected static String retrieveBaseClass(ContractVerifierConfigProperties properties, String includedDirectoryRelativePath) {
|
||||
String contractPathAsPackage = includedDirectoryRelativePath.
|
||||
replace(File.separator, ".")
|
||||
String contractPackage = includedDirectoryRelativePath.
|
||||
replace(File.separator, SEPARATOR)
|
||||
// package mapping takes super precedence
|
||||
if (properties.baseClassMappings) {
|
||||
Map.Entry<String, String> mapping = properties.baseClassMappings.
|
||||
find { String pattern, String fqn ->
|
||||
return contractPathAsPackage.matches(pattern)
|
||||
}
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Matching pattern for contract package [${contractPathAsPackage}] with setup ${properties.baseClassMappings} is [${mapping}]")
|
||||
}
|
||||
if (mapping) {
|
||||
return mapping.value
|
||||
}
|
||||
}
|
||||
if (!properties.packageWithBaseClasses) {
|
||||
return properties.baseClassForTests
|
||||
}
|
||||
String generatedClassName =
|
||||
generateDefaultBaseClassName(contractPackage, properties)
|
||||
return "${generatedClassName}Base"
|
||||
}
|
||||
|
||||
private static String generateDefaultBaseClassName(String classPackage, ContractVerifierConfigProperties properties) {
|
||||
String[] splitPackage = NamesUtil.convertIllegalPackageChars(classPackage).
|
||||
split(SEPARATOR)
|
||||
if (splitPackage.size() > 1) {
|
||||
String last = NamesUtil.capitalize(splitPackage[-1])
|
||||
String butLast = NamesUtil.capitalize(splitPackage[-2])
|
||||
return "${properties.packageWithBaseClasses}.${butLast}${last}"
|
||||
}
|
||||
return "${properties.packageWithBaseClasses}.${NamesUtil.capitalize(splitPackage[0])}"
|
||||
}
|
||||
|
||||
ClassBuilder addImport(String importToAdd) {
|
||||
imports << importToAdd
|
||||
return this
|
||||
}
|
||||
|
||||
ClassBuilder addImports(List<String> importsToAdd) {
|
||||
imports.addAll(importsToAdd)
|
||||
return this
|
||||
}
|
||||
|
||||
ClassBuilder addStaticImports(List<String> importsToAdd) {
|
||||
staticImports.addAll(importsToAdd)
|
||||
return this
|
||||
}
|
||||
|
||||
ClassBuilder addStaticImport(String importToAdd) {
|
||||
staticImports << importToAdd
|
||||
return this
|
||||
}
|
||||
|
||||
ClassBuilder addMethod(MethodBuilder methodBuilder) {
|
||||
methods << methodBuilder
|
||||
return this
|
||||
}
|
||||
|
||||
ClassBuilder addField(String fieldToAdd) {
|
||||
fields << appendColonIfJUniTest(fieldToAdd)
|
||||
return this
|
||||
}
|
||||
|
||||
ClassBuilder addField(List<String> fieldsToAdd) {
|
||||
fields.addAll(fieldsToAdd.collect { appendColonIfJUniTest(it) })
|
||||
return this
|
||||
}
|
||||
|
||||
ClassBuilder addRule(String ruleClass) {
|
||||
imports << ruleClass
|
||||
rules << NamesUtil.afterLastDot(ruleClass)
|
||||
return this
|
||||
}
|
||||
|
||||
String build() {
|
||||
BlockBuilder clazz = new BlockBuilder("\t")
|
||||
.addLine("package $packageName$lang.lineSuffix")
|
||||
.addEmptyLine()
|
||||
|
||||
imports.sort().each {
|
||||
clazz.addLine("import $it$lang.lineSuffix")
|
||||
}
|
||||
if (!imports.empty) {
|
||||
clazz.addEmptyLine()
|
||||
}
|
||||
|
||||
staticImports.sort().each {
|
||||
clazz.addLine("import static $it$lang.lineSuffix")
|
||||
}
|
||||
if (!staticImports.empty) {
|
||||
clazz.addEmptyLine()
|
||||
}
|
||||
|
||||
classLevelAnnotations.sort().each {
|
||||
clazz.addLine(it)
|
||||
}
|
||||
|
||||
def classLine = "${lang.classModifier}class $className"
|
||||
if (baseClass) {
|
||||
classLine += " extends $baseClass"
|
||||
}
|
||||
clazz.addLine(classLine + ' {')
|
||||
clazz.addEmptyLine()
|
||||
|
||||
clazz.startBlock()
|
||||
rules.sort().each {
|
||||
clazz.addLine("@Rule")
|
||||
clazz.
|
||||
addLine("public $it ${NamesUtil.camelCase(it)} = new $it()$lang.lineSuffix")
|
||||
}
|
||||
clazz.endBlock()
|
||||
if (!rules.empty) {
|
||||
clazz.addEmptyLine()
|
||||
}
|
||||
|
||||
clazz.startBlock()
|
||||
fields.sort().each {
|
||||
clazz.addLine(it)
|
||||
}
|
||||
if (!fields.empty) {
|
||||
clazz.addEmptyLine()
|
||||
}
|
||||
clazz.endBlock()
|
||||
|
||||
methods.each {
|
||||
clazz.addBlock(it)
|
||||
}
|
||||
|
||||
clazz.addLine('}')
|
||||
clazz.toString()
|
||||
}
|
||||
|
||||
void addClassLevelAnnotation(String annotation) {
|
||||
classLevelAnnotations << annotation
|
||||
}
|
||||
|
||||
private String appendColonIfJUniTest(String field) {
|
||||
if (isJUnitType(field)) {
|
||||
return "$field;"
|
||||
}
|
||||
return field
|
||||
}
|
||||
|
||||
private boolean isJUnitType(String field) {
|
||||
TestFramework.JUNIT == lang || TestFramework.JUNIT5 == lang && !field.endsWith(';')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 ClassMetaData extends Acceptor {
|
||||
|
||||
ClassMetaData setupLineEnding();
|
||||
|
||||
ClassMetaData setupLabelPrefix();
|
||||
|
||||
ClassMetaData packageDefinition();
|
||||
|
||||
ClassMetaData modifier();
|
||||
|
||||
ClassMetaData suffix();
|
||||
|
||||
ClassMetaData parentClass();
|
||||
|
||||
ClassMetaData className();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.springframework.cloud.contract.verifier.builder;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Used to return the {@link Class} against which the type of the element should be
|
||||
* verified using <code>instanceof</code> in generated response assertions.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public interface ClassVerifier {
|
||||
|
||||
default Class classToCheck(Object elementFromBody) {
|
||||
if (elementFromBody instanceof List) {
|
||||
return List.class;
|
||||
}
|
||||
else if (elementFromBody instanceof Set) {
|
||||
return Set.class;
|
||||
}
|
||||
else if (elementFromBody instanceof Map) {
|
||||
return Map.class;
|
||||
}
|
||||
return elementFromBody.getClass();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,9 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.contract.verifier.builder
|
||||
|
||||
import groovy.transform.CompileStatic
|
||||
package org.springframework.cloud.contract.verifier.builder;
|
||||
|
||||
/**
|
||||
* Describes the type of communication
|
||||
@@ -24,7 +22,8 @@ import groovy.transform.CompileStatic
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 2.1.0
|
||||
*/
|
||||
@CompileStatic
|
||||
enum CommunicationType {
|
||||
REQUEST, RESPONSE, INPUT, OUTPUT
|
||||
public enum CommunicationType {
|
||||
|
||||
REQUEST, RESPONSE, INPUT, OUTPUT;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* 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 java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import static org.apache.commons.text.StringEscapeUtils.escapeJava;
|
||||
|
||||
interface ComparisonBuilder {
|
||||
|
||||
ComparisonBuilder JAVA_HTTP_INSTANCE = () -> RestAssuredBodyParser.INSTANCE;
|
||||
|
||||
ComparisonBuilder JAVA_MESSAGING_INSTANCE = () -> JavaMessagingBodyParser.INSTANCE;
|
||||
|
||||
default String createComparison(Object headerValue) {
|
||||
if (headerValue instanceof Pattern) {
|
||||
return matches((Pattern) headerValue);
|
||||
}
|
||||
else if (headerValue instanceof Number) {
|
||||
return isEqualTo((Number) headerValue);
|
||||
}
|
||||
String escapedHeader = convertUnicodeEscapesIfRequired(headerValue.toString());
|
||||
return isEqualTo(escapedHeader);
|
||||
}
|
||||
|
||||
default String createUnescapedComparison(Object headerValue) {
|
||||
if (headerValue instanceof Pattern) {
|
||||
return createComparison((Pattern) headerValue);
|
||||
}
|
||||
else if (headerValue instanceof Number) {
|
||||
return isEqualTo((Number) headerValue);
|
||||
}
|
||||
return isEqualTo(headerValue.toString());
|
||||
}
|
||||
|
||||
default String assertThat(String object) {
|
||||
return "assertThat(" + object + ")";
|
||||
}
|
||||
|
||||
default String assertThatIsNotNull(String object) {
|
||||
return assertThat(object) + isNotNull();
|
||||
}
|
||||
|
||||
default String assertThat(String object, Object valueToCompareAgainst) {
|
||||
return assertThat(object) + createComparison(valueToCompareAgainst);
|
||||
}
|
||||
|
||||
default String assertThatUnescaped(String object, Object valueToCompareAgainst) {
|
||||
return assertThat(object) + createUnescapedComparison(valueToCompareAgainst);
|
||||
}
|
||||
|
||||
default String isEqualTo(String escapedHeaderValue) {
|
||||
return isEqualToUnquoted(bodyParser().quotedShortText(escapedHeaderValue));
|
||||
}
|
||||
|
||||
default String isEqualToUnquoted(String unquoted) {
|
||||
return ".isEqualTo(" + unquoted + ")";
|
||||
}
|
||||
|
||||
default String isEqualTo(Number number) {
|
||||
return ".isEqualTo(" + number.toString() + ")";
|
||||
}
|
||||
|
||||
default String isNotNull() {
|
||||
return ".isNotNull()";
|
||||
}
|
||||
|
||||
default String matches(Pattern pattern) {
|
||||
String escapedPattern = StringEscapeUtils.escapeJava(pattern.pattern());
|
||||
return ".matches(" + bodyParser().quotedEscapedShortText(escapedPattern) + ")";
|
||||
}
|
||||
|
||||
default String matches(String pattern) {
|
||||
return ".matches(" + bodyParser().quotedShortText(pattern) + ")";
|
||||
}
|
||||
|
||||
default String matchesEscaped(String pattern) {
|
||||
return ".matches(" + bodyParser().quotedEscapedShortText(pattern) + ")";
|
||||
}
|
||||
|
||||
default String convertUnicodeEscapesIfRequired(String json) {
|
||||
String unescapedJson = StringEscapeUtils.unescapeJson(json);
|
||||
return escapeJava(unescapedJson);
|
||||
}
|
||||
|
||||
BodyParser bodyParser();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* 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.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty;
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter;
|
||||
|
||||
final class ContentHelper {
|
||||
|
||||
/**
|
||||
* Depending on the object type extracts the test side values and combines them into a
|
||||
* String representation. Will not try to guess the type of the value of the header
|
||||
* (e.g. if it's a JSON).
|
||||
*/
|
||||
static String getTestSideForNonBodyValue(Object object) {
|
||||
if (object instanceof ExecutionProperty) {
|
||||
return getTestSideValue(object);
|
||||
}
|
||||
return quotedAndEscaped(
|
||||
MapConverter.getTestSideValuesForNonBody(object).toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Depending on the object type extracts the test side values and combines them into a
|
||||
* String representation
|
||||
*/
|
||||
private static String getTestSideValue(Object object) {
|
||||
if (object instanceof ExecutionProperty) {
|
||||
return object.toString();
|
||||
}
|
||||
return '"' + MapConverter.getTestSideValues(object).toString() + '"';
|
||||
}
|
||||
|
||||
private static String quotedAndEscaped(String string) {
|
||||
return '"' + StringEscapeUtils.escapeJava(string) + '"';
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* 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 java.util.regex.Pattern;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.Cookies;
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty;
|
||||
import org.springframework.cloud.contract.spec.internal.NotToEscapePattern;
|
||||
import org.springframework.cloud.contract.spec.internal.Response;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter;
|
||||
|
||||
interface CookieElementProcessor {
|
||||
|
||||
ComparisonBuilder comparisonBuilder();
|
||||
|
||||
default void processCookies(SingleContractMetadata metadata) {
|
||||
Response response = metadata.getContract().getResponse();
|
||||
Cookies cookies = response.getCookies();
|
||||
cookies.executeForEachCookie(cookie -> processCookieElement(cookie.getKey(),
|
||||
cookie.getServerValue() instanceof NotToEscapePattern
|
||||
? cookie.getServerValue()
|
||||
: MapConverter.getTestSideValues(cookie.getServerValue())));
|
||||
blockBuilder().addEndingIfNotPresent();
|
||||
}
|
||||
|
||||
BlockBuilder blockBuilder();
|
||||
|
||||
default void processCookieElement(String property, Object value) {
|
||||
if (value instanceof NotToEscapePattern) {
|
||||
verifyCookieNotNull(property);
|
||||
blockBuilder()
|
||||
.addIndented(comparisonBuilder().assertThat(cookieValue(property))
|
||||
+ comparisonBuilder().matches(((NotToEscapePattern) value)
|
||||
.getServerValue().pattern().replace("\\", "\\\\")));
|
||||
}
|
||||
else if (value instanceof String || value instanceof Pattern) {
|
||||
verifyCookieNotNull(property);
|
||||
blockBuilder().addIndented(
|
||||
comparisonBuilder().assertThat(cookieValue(property), value));
|
||||
}
|
||||
else if (value instanceof Number) {
|
||||
verifyCookieNotNull(property);
|
||||
blockBuilder().addIndented(
|
||||
comparisonBuilder().assertThat(cookieValue(property), value));
|
||||
}
|
||||
else if (value instanceof ExecutionProperty) {
|
||||
verifyCookieNotNull(property);
|
||||
blockBuilder().addIndented(
|
||||
((ExecutionProperty) value).insertValue(cookieValue(property)));
|
||||
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
processCookieElement(property, value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
default void verifyCookieNotNull(String key) {
|
||||
blockBuilder().addLineWithEnding(
|
||||
comparisonBuilder().assertThatIsNotNull(cookieKey(key)));
|
||||
}
|
||||
|
||||
String cookieKey(String key);
|
||||
|
||||
default String cookieValue(String key) {
|
||||
return cookieKey(key);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
class CustomImports implements Imports {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
CustomImports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
Arrays.stream(this.generatedClassMetaData.configProperties.getImports())
|
||||
.forEach(s -> this.blockBuilder.addLineWithEnding("import " + s));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties.getImports() != null
|
||||
&& this.generatedClassMetaData.configProperties.getImports().length > 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
class CustomStaticImports implements Imports {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
CustomStaticImports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
Arrays.stream(this.generatedClassMetaData.configProperties.getStaticImports())
|
||||
.forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties.getStaticImports() != null
|
||||
&& this.generatedClassMetaData.configProperties
|
||||
.getStaticImports().length > 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* 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.verifier.config.ContractVerifierConfigProperties;
|
||||
|
||||
interface DefaultBaseClassProvider {
|
||||
|
||||
GeneratedClassMetaData generatedClassMetaData();
|
||||
|
||||
BaseClassProvider baseClassProvider();
|
||||
|
||||
default String fqnBaseClass() {
|
||||
ContractVerifierConfigProperties properties = generatedClassMetaData().configProperties;
|
||||
String includedDirectoryRelativePath = generatedClassMetaData().includedDirectoryRelativePath;
|
||||
return baseClassProvider().retrieveBaseClass(properties,
|
||||
includedDirectoryRelativePath);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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 static org.springframework.cloud.contract.verifier.util.NamesUtil.capitalize;
|
||||
|
||||
interface DefaultClassMetadata extends ClassMetaData, DefaultBaseClassProvider {
|
||||
|
||||
@Override
|
||||
default ClassMetaData packageDefinition() {
|
||||
blockBuilder().addLineWithEnding(
|
||||
"package " + generatedClassMetaData().generatedClassData.classPackage);
|
||||
return this;
|
||||
}
|
||||
|
||||
GeneratedClassMetaData generatedClassMetaData();
|
||||
|
||||
BaseClassProvider baseClassProvider();
|
||||
|
||||
BlockBuilder blockBuilder();
|
||||
|
||||
@Override
|
||||
default ClassMetaData className() {
|
||||
String className = capitalize(
|
||||
generatedClassMetaData().generatedClassData.className);
|
||||
blockBuilder().addAtTheEnd(className);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.util.StringUtils;
|
||||
|
||||
class DefaultImports implements Imports, DefaultBaseClassProvider {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private final BaseClassProvider baseClassProvider;
|
||||
|
||||
DefaultImports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
this.baseClassProvider = new BaseClassProvider();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
String fqnBaseClass = fqnBaseClass();
|
||||
if (StringUtils.hasText(fqnBaseClass)) {
|
||||
this.blockBuilder.addLineWithEnding("import " + fqnBaseClass);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeneratedClassMetaData generatedClassMetaData() {
|
||||
return this.generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseClassProvider baseClassProvider() {
|
||||
return this.baseClassProvider;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class DefaultJsonStaticImports implements Imports {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] IMPORTS = {
|
||||
"com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson" };
|
||||
|
||||
DefaultJsonStaticImports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
Arrays.stream(IMPORTS)
|
||||
.forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.listOfFiles.stream()
|
||||
.anyMatch(metadata -> metadata.getConvertedContractWithMetadata().stream()
|
||||
.anyMatch(SingleContractMetadata::isJson));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
class DefaultStaticImports implements Imports {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private static final String[] IMPORTS = {
|
||||
"org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat",
|
||||
"org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*" };
|
||||
|
||||
DefaultStaticImports(BlockBuilder blockBuilder) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
Arrays.stream(IMPORTS)
|
||||
.forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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.verifier.config.TestMode;
|
||||
|
||||
interface ExplicitAcceptor {
|
||||
|
||||
default boolean acceptType(GeneratedClassMetaData generatedClassMetaData) {
|
||||
return generatedClassMetaData.configProperties.getTestMode() == TestMode.EXPLICIT;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,52 +0,0 @@
|
||||
/*
|
||||
* 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 groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
|
||||
/**
|
||||
* A {@link JUnitMethodBodyBuilder} implementation that uses Rest Assured in explicit mode
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
*
|
||||
* @since 1.0.3
|
||||
*/
|
||||
@TypeChecked
|
||||
@PackageScope
|
||||
class ExplicitJUnitMethodBodyBuilder extends RestAssuredJUnitMethodBodyBuilder {
|
||||
|
||||
ExplicitJUnitMethodBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String returnedResponseType() {
|
||||
return "Response"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String returnedRequestType() {
|
||||
return "RequestSpecification"
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.verifier.file.SingleContractMetadata;
|
||||
|
||||
class ExplicitRequestGiven implements Given, ExplicitAcceptor {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
ExplicitRequestGiven(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = metaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<Given> apply(SingleContractMetadata metadata) {
|
||||
this.blockBuilder.addIndented("RequestSpecification request = given()");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return acceptType(this.generatedClassMetaData);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.verifier.file.SingleContractMetadata;
|
||||
|
||||
class ExplicitResponseWhen implements When, ExplicitAcceptor {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
ExplicitResponseWhen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = metaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<When> apply(SingleContractMetadata metadata) {
|
||||
this.blockBuilder.addIndented("Response response = given().spec(request)");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return acceptType(this.generatedClassMetaData);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestMode;
|
||||
|
||||
class ExplicitRestAssuredImports implements Imports, RestAssuredVerifier {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] REST_ASSURED_2_IMPORTS = {
|
||||
"com.jayway.restassured.specification.RequestSpecification",
|
||||
"com.jayway.restassured.response.Response" };
|
||||
|
||||
private static final String[] REST_ASSURED_3_IMPORTS = {
|
||||
"io.restassured.specification.RequestSpecification",
|
||||
"io.restassured.response.Response" };
|
||||
|
||||
ExplicitRestAssuredImports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
Arrays.stream(
|
||||
isRestAssured2Present() ? REST_ASSURED_2_IMPORTS : REST_ASSURED_3_IMPORTS)
|
||||
.forEach(s -> this.blockBuilder.addLineWithEnding("import " + s));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestMode() == TestMode.EXPLICIT
|
||||
&& this.generatedClassMetaData.isAnyHttp();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestMode;
|
||||
|
||||
class ExplicitRestAssuredStaticImports implements Imports, RestAssuredVerifier {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] REST_ASSURED_2_IMPORTS = {
|
||||
"com.jayway.restassured.RestAssured.*" };
|
||||
|
||||
private static final String[] REST_ASSURED_3_IMPORTS = {
|
||||
"io.restassured.RestAssured.*" };
|
||||
|
||||
ExplicitRestAssuredStaticImports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
Arrays.stream(
|
||||
isRestAssured2Present() ? REST_ASSURED_2_IMPORTS : REST_ASSURED_3_IMPORTS)
|
||||
.forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestMode() == TestMode.EXPLICIT
|
||||
&& this.generatedClassMetaData.isAnyHttp();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 Field extends Visitor<Field> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
class FieldBuilder {
|
||||
|
||||
private final ClassBodyBuilder parentBuilder;
|
||||
|
||||
private final BlockBuilder builder;
|
||||
|
||||
private final GeneratedClassMetaData metaData;
|
||||
|
||||
FieldBuilder(ClassBodyBuilder parentBuilder) {
|
||||
this.parentBuilder = parentBuilder;
|
||||
this.builder = parentBuilder.blockBuilder;
|
||||
this.metaData = parentBuilder.generatedClassMetaData;
|
||||
}
|
||||
|
||||
FieldBuilder messaging() {
|
||||
this.parentBuilder.field(new MessagingFields(this.builder, this.metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
ClassBodyBuilder build() {
|
||||
return this.parentBuilder;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
/*
|
||||
* Copyright 2013-2018 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
|
||||
|
||||
/**
|
||||
* @author Marcin Grzejszczak
|
||||
* @since
|
||||
*/
|
||||
class GeneratedClassDataForMethod {
|
||||
final SingleTestGenerator.GeneratedClassData generatedClassData
|
||||
final String methodName
|
||||
|
||||
GeneratedClassDataForMethod(SingleTestGenerator.GeneratedClassData generatedClassData,
|
||||
String methodName) {
|
||||
this.generatedClassData = generatedClassData
|
||||
this.methodName = methodName
|
||||
}
|
||||
|
||||
private SingleTestGenerator.GeneratedClassData assertClassData() {
|
||||
if (this.generatedClassData == null) {
|
||||
throw new IllegalStateException("No metadata was found for the generated test class")
|
||||
}
|
||||
return this.generatedClassData
|
||||
}
|
||||
|
||||
String className() {
|
||||
return assertClassData().className
|
||||
}
|
||||
|
||||
java.nio.file.Path testClassPath() {
|
||||
return assertClassData().testClassPath
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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 java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* POJO that wraps data for a given generated method.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 2.1.0
|
||||
*/
|
||||
public class GeneratedClassDataForMethod {
|
||||
|
||||
private final SingleTestGenerator.GeneratedClassData generatedClassData;
|
||||
|
||||
private final String methodName;
|
||||
|
||||
public GeneratedClassDataForMethod(
|
||||
SingleTestGenerator.GeneratedClassData generatedClassData,
|
||||
String methodName) {
|
||||
this.generatedClassData = generatedClassData;
|
||||
this.methodName = methodName;
|
||||
}
|
||||
|
||||
private SingleTestGenerator.GeneratedClassData assertClassData() {
|
||||
if (this.generatedClassData == null) {
|
||||
throw new IllegalStateException(
|
||||
"No metadata was found for the generated test class");
|
||||
}
|
||||
return this.generatedClassData;
|
||||
}
|
||||
|
||||
public String className() {
|
||||
return assertClassData().className;
|
||||
}
|
||||
|
||||
public Path testClassPath() {
|
||||
return assertClassData().testClassPath;
|
||||
}
|
||||
|
||||
public final SingleTestGenerator.GeneratedClassData getGeneratedClassData() {
|
||||
return generatedClassData;
|
||||
}
|
||||
|
||||
public final String getMethodName() {
|
||||
return methodName;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties;
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
/**
|
||||
* All meta data required to generate a test class.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 2.2.0
|
||||
*/
|
||||
class GeneratedClassMetaData {
|
||||
|
||||
final ContractVerifierConfigProperties configProperties;
|
||||
|
||||
final Collection<ContractMetadata> listOfFiles;
|
||||
|
||||
final String includedDirectoryRelativePath;
|
||||
|
||||
final SingleTestGenerator.GeneratedClassData generatedClassData;
|
||||
|
||||
GeneratedClassMetaData(ContractVerifierConfigProperties configProperties,
|
||||
Collection<ContractMetadata> listOfFiles,
|
||||
String includedDirectoryRelativePath,
|
||||
SingleTestGenerator.GeneratedClassData generatedClassData) {
|
||||
this.configProperties = configProperties;
|
||||
this.listOfFiles = listOfFiles;
|
||||
this.includedDirectoryRelativePath = includedDirectoryRelativePath;
|
||||
this.generatedClassData = generatedClassData;
|
||||
}
|
||||
|
||||
Collection<SingleContractMetadata> toSingleContractMetadata() {
|
||||
return this.listOfFiles.stream()
|
||||
.flatMap(metadata -> metadata.getConvertedContractWithMetadata().stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
boolean isAnyJson() {
|
||||
return toSingleContractMetadata().stream()
|
||||
.anyMatch(SingleContractMetadata::isJson);
|
||||
}
|
||||
|
||||
boolean isAnyIgnored() {
|
||||
return toSingleContractMetadata().stream()
|
||||
.anyMatch(SingleContractMetadata::isIgnored);
|
||||
}
|
||||
|
||||
boolean isAnyXml() {
|
||||
return toSingleContractMetadata().stream()
|
||||
.anyMatch(SingleContractMetadata::isXml);
|
||||
}
|
||||
|
||||
boolean isAnyHttp() {
|
||||
return toSingleContractMetadata().stream()
|
||||
.anyMatch(SingleContractMetadata::isHttp);
|
||||
}
|
||||
|
||||
boolean isAnyMessaging() {
|
||||
return toSingleContractMetadata().stream()
|
||||
.anyMatch(SingleContractMetadata::isMessaging);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,28 +14,25 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.cloud.contract.verifier.builder
|
||||
package org.springframework.cloud.contract.verifier.builder;
|
||||
|
||||
/**
|
||||
* Used to return the {@link Class} against which the type of the element should be verified
|
||||
* using <code>instanceof</code> in generated response assertions.
|
||||
* Contents of the generated test.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @since 2.1.0
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 2.2.0
|
||||
*/
|
||||
trait ClassVerifier {
|
||||
public class GeneratedTestClass {
|
||||
|
||||
Class classToCheck(Object elementFromBody) {
|
||||
switch (elementFromBody.getClass()) {
|
||||
case List:
|
||||
return List
|
||||
case Set:
|
||||
return Set
|
||||
case Map:
|
||||
return Map
|
||||
default:
|
||||
return elementFromBody.class
|
||||
}
|
||||
final BlockBuilder blockBuilder;
|
||||
|
||||
GeneratedTestClass(BlockBuilder blockBuilder) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
}
|
||||
|
||||
public String asClassString() {
|
||||
return this.blockBuilder.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A generated test class consists of the class meta data (e.g. packages, imports) fields
|
||||
* and methods. The latter are generated via the {@link ClassBodyBuilder}.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma
|
||||
* @author Marcin Grzejszczak
|
||||
* @since 2.2.0
|
||||
*/
|
||||
class GeneratedTestClassBuilder {
|
||||
|
||||
private List<ClassMetaData> metaData = new LinkedList<>();
|
||||
|
||||
private List<Imports> imports = new LinkedList<>();
|
||||
|
||||
private List<Imports> staticImports = new LinkedList<>();
|
||||
|
||||
private List<ClassAnnotation> annotations = new LinkedList<>();
|
||||
|
||||
private ClassBodyBuilder classBodyBuilder;
|
||||
|
||||
final BlockBuilder blockBuilder;
|
||||
|
||||
final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private GeneratedTestClassBuilder(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
static GeneratedTestClassBuilder builder(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
return new GeneratedTestClassBuilder(blockBuilder, generatedClassMetaData);
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder metaData(ClassMetaData metaData) {
|
||||
this.metaData.add(metaData);
|
||||
return this;
|
||||
}
|
||||
|
||||
MetaDataBuilder metaData() {
|
||||
return new MetaDataBuilder(this);
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder metaData(ClassMetaData... metaData) {
|
||||
return metaData(Arrays.asList(metaData));
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder metaData(List<ClassMetaData> metaData) {
|
||||
this.metaData.addAll(metaData);
|
||||
return this;
|
||||
}
|
||||
|
||||
ImportsBuilder imports() {
|
||||
return new ImportsBuilder(this);
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder imports(Imports imports) {
|
||||
this.imports.add(imports);
|
||||
return this;
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder imports(Imports... imports) {
|
||||
return imports(Arrays.asList(imports));
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder imports(List<Imports> imports) {
|
||||
this.imports.addAll(imports);
|
||||
return this;
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder staticImports(Imports imports) {
|
||||
this.staticImports.add(imports);
|
||||
return this;
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder staticImports(Imports... imports) {
|
||||
return staticImports(Arrays.asList(imports));
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder staticImports(List<Imports> imports) {
|
||||
this.staticImports.addAll(imports);
|
||||
return this;
|
||||
}
|
||||
|
||||
ClassAnnotationsBuilder classAnnotations() {
|
||||
return new ClassAnnotationsBuilder(this);
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder classAnnotations(ClassAnnotation... annotations) {
|
||||
List<ClassAnnotation> classAnnotations = Arrays.asList(annotations);
|
||||
this.annotations.addAll(classAnnotations);
|
||||
return this;
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder classBodyBuilder(ClassBodyBuilder classBodyBuilder) {
|
||||
this.classBodyBuilder = classBodyBuilder;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* From a matching {@link ClassMetaData} given the present input data, builds a
|
||||
* generated test class.
|
||||
* @return generated test class
|
||||
*/
|
||||
GeneratedTestClass build() {
|
||||
// picks a matching class meta data
|
||||
ClassMetaData classMetaData = this.metaData.stream().filter(Acceptor::accept)
|
||||
.findFirst().orElseThrow(() -> new IllegalStateException(
|
||||
"There is no matching class meta data"));
|
||||
classMetaData.setupLineEnding().setupLabelPrefix()
|
||||
// package com.example
|
||||
.packageDefinition();
|
||||
// \n
|
||||
this.blockBuilder.addEmptyLine();
|
||||
// import ... \n
|
||||
visit(this.imports);
|
||||
// import static ... \n
|
||||
visit(this.staticImports);
|
||||
// @Test ... \n
|
||||
visitWithNoEnding(this.annotations);
|
||||
// @formatter:off
|
||||
// public
|
||||
this.blockBuilder.append(classMetaData::modifier)
|
||||
// class
|
||||
.appendWithSpace("class")
|
||||
// Foo
|
||||
.appendWithSpace(classMetaData::className)
|
||||
// Spec
|
||||
.append(classMetaData::suffix)
|
||||
// extends Parent
|
||||
.appendWithSpace(classMetaData::parentClass);
|
||||
// public class FooSpec extends Parent
|
||||
// @formatter:on
|
||||
this.classBodyBuilder.build();
|
||||
return new GeneratedTestClass(this.blockBuilder);
|
||||
}
|
||||
|
||||
void visit(List<? extends Visitor> list) {
|
||||
visit(list, true);
|
||||
}
|
||||
|
||||
void visitWithNoEnding(List<? extends Visitor> list) {
|
||||
visit(list, false);
|
||||
}
|
||||
|
||||
private void visit(List<? extends Visitor> list, boolean addEnding) {
|
||||
List<Visitor> elements = list.stream().filter(Acceptor::accept)
|
||||
.collect(Collectors.toList());
|
||||
elements.forEach(OurCallable::call);
|
||||
if (addEnding) {
|
||||
this.blockBuilder.addEndingIfNotPresent();
|
||||
}
|
||||
if (!elements.isEmpty()) {
|
||||
this.blockBuilder.addEmptyLine();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.FromFileProperty;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class GenericBinaryBodyThen implements Then {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final BodyAssertionLineCreator bodyAssertionLineCreator;
|
||||
|
||||
private final BodyParser bodyParser;
|
||||
|
||||
private final ComparisonBuilder comparisonBuilder;
|
||||
|
||||
GenericBinaryBodyThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData,
|
||||
BodyParser bodyParser, ComparisonBuilder comparisonBuilder) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.comparisonBuilder = comparisonBuilder;
|
||||
this.bodyAssertionLineCreator = new BodyAssertionLineCreator(blockBuilder,
|
||||
metaData, bodyParser.byteArrayString(), this.comparisonBuilder);
|
||||
this.bodyParser = bodyParser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<Then> apply(SingleContractMetadata metadata) {
|
||||
Object responseBody = this.bodyParser.responseBody(metadata).getServerValue();
|
||||
byteResponseBodyCheck(metadata, (FromFileProperty) responseBody);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void byteResponseBodyCheck(SingleContractMetadata metadata,
|
||||
FromFileProperty convertedResponseBody) {
|
||||
this.bodyAssertionLineCreator.appendBodyAssertionLine(metadata, "",
|
||||
convertedResponseBody);
|
||||
this.blockBuilder.addEndingIfNotPresent();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
Object responseBody = this.bodyParser.responseBody(metadata).getServerValue();
|
||||
if (!(responseBody instanceof FromFileProperty)) {
|
||||
return false;
|
||||
}
|
||||
return ((FromFileProperty) responseBody).isByte();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
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 GenericHttpBodyThen implements Then, BodyMethodVisitor {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final BodyParser bodyParser;
|
||||
|
||||
private final TemplateProcessor templateProcessor;
|
||||
|
||||
private final ComparisonBuilder comparisonBuilder;
|
||||
|
||||
private final List<Then> thens = new LinkedList<>();
|
||||
|
||||
GenericHttpBodyThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData,
|
||||
BodyParser bodyParser, ComparisonBuilder comparisonBuilder) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.bodyParser = bodyParser;
|
||||
this.comparisonBuilder = comparisonBuilder;
|
||||
this.templateProcessor = new HandlebarsTemplateProcessor();
|
||||
this.thens.addAll(Arrays.asList(
|
||||
new GenericBinaryBodyThen(blockBuilder, metaData, this.bodyParser,
|
||||
comparisonBuilder),
|
||||
new GenericTextBodyThen(blockBuilder, metaData, this.bodyParser,
|
||||
this.comparisonBuilder),
|
||||
new GenericJsonBodyThen(blockBuilder, metaData, this.bodyParser,
|
||||
this.comparisonBuilder),
|
||||
new GenericXmlBodyThen(blockBuilder, this.bodyParser)));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<Then> apply(SingleContractMetadata metadata) {
|
||||
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;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return metadata.getContract().getResponse().getBody() != null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* 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 java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import org.springframework.cloud.contract.spec.ContractTemplate;
|
||||
import org.springframework.cloud.contract.spec.internal.BodyMatchers;
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty;
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
import org.springframework.cloud.contract.verifier.template.HandlebarsTemplateProcessor;
|
||||
import org.springframework.cloud.contract.verifier.template.TemplateProcessor;
|
||||
import org.springframework.cloud.contract.verifier.util.ContentType;
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.DEFINED;
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.FORM;
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.JSON;
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.TEXT;
|
||||
|
||||
class GenericJsonBodyThen implements Then {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private final BodyParser bodyParser;
|
||||
|
||||
private final BodyAssertionLineCreator bodyAssertionLineCreator;
|
||||
|
||||
private final TemplateProcessor templateProcessor;
|
||||
|
||||
private final ContractTemplate contractTemplate;
|
||||
|
||||
private final ComparisonBuilder comparisonBuilder;
|
||||
|
||||
GenericJsonBodyThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData,
|
||||
BodyParser bodyParser, ComparisonBuilder comparisonBuilder) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.bodyParser = bodyParser;
|
||||
this.comparisonBuilder = comparisonBuilder;
|
||||
this.bodyAssertionLineCreator = new BodyAssertionLineCreator(blockBuilder,
|
||||
metaData, this.bodyParser.byteArrayString(), this.comparisonBuilder);
|
||||
this.generatedClassMetaData = metaData;
|
||||
this.templateProcessor = new HandlebarsTemplateProcessor();
|
||||
this.contractTemplate = new HandlebarsTemplateProcessor();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<Then> apply(SingleContractMetadata metadata) {
|
||||
BodyMatchers bodyMatchers = this.bodyParser.responseBodyMatchers(metadata);
|
||||
Object convertedResponseBody = this.bodyParser.convertResponseBody(metadata);
|
||||
ContentType contentType = metadata.getOutputTestContentType();
|
||||
if (TEXT != contentType && FORM != contentType && DEFINED != contentType) {
|
||||
boolean dontParseStrings = contentType == JSON
|
||||
&& convertedResponseBody instanceof Map;
|
||||
Function parsingClosure = dontParseStrings ? Function.identity()
|
||||
: MapConverter.JSON_PARSING_FUNCTION;
|
||||
convertedResponseBody = MapConverter.getTestSideValues(convertedResponseBody,
|
||||
parsingClosure);
|
||||
}
|
||||
else {
|
||||
convertedResponseBody = StringEscapeUtils
|
||||
.escapeJava(convertedResponseBody.toString());
|
||||
}
|
||||
addJsonBodyVerification(metadata, convertedResponseBody, bodyMatchers);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void addJsonBodyVerification(SingleContractMetadata contractMetadata,
|
||||
Object responseBody, BodyMatchers bodyMatchers) {
|
||||
JsonBodyVerificationBuilder jsonBodyVerificationBuilder = new JsonBodyVerificationBuilder(
|
||||
this.generatedClassMetaData.configProperties, this.templateProcessor,
|
||||
this.contractTemplate, contractMetadata.getContract(),
|
||||
Optional.of(this.blockBuilder.getLineEnding()),
|
||||
bodyParser::postProcessJsonPath);
|
||||
// TODO: Refactor spock from should comment out bdd blocks
|
||||
Object convertedResponseBody = jsonBodyVerificationBuilder
|
||||
.addJsonResponseBodyCheck(this.blockBuilder, responseBody, bodyMatchers,
|
||||
this.bodyParser.responseAsString(),
|
||||
this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() != TestFramework.SPOCK);
|
||||
if (!(convertedResponseBody instanceof Map
|
||||
|| convertedResponseBody instanceof List)) {
|
||||
simpleTextResponseBodyCheck(contractMetadata, convertedResponseBody);
|
||||
}
|
||||
processBodyElement("", "", convertedResponseBody);
|
||||
}
|
||||
|
||||
private void processBodyElement(String oldProp, String property, Object value) {
|
||||
String propDiff = subtract(property, oldProp);
|
||||
String prop = wrappedWithBracketsForDottedProp(propDiff);
|
||||
String mergedProp = StringUtils.hasText(property) ? oldProp + "." + prop : "";
|
||||
if (value instanceof ExecutionProperty) {
|
||||
processBodyElement(mergedProp, (ExecutionProperty) value);
|
||||
}
|
||||
else if (value instanceof Map.Entry) {
|
||||
processBodyElement(mergedProp, (Map.Entry) value);
|
||||
}
|
||||
else if (value instanceof Map) {
|
||||
processBodyElement(mergedProp, (Map) value);
|
||||
}
|
||||
else if (value instanceof List) {
|
||||
processBodyElement(mergedProp, (List) value);
|
||||
}
|
||||
}
|
||||
|
||||
private void processBodyElement(String property, ExecutionProperty exec) {
|
||||
this.blockBuilder.addLineWithEnding(exec.insertValue(this.bodyParser
|
||||
.postProcessJsonPath("parsedJson.read(\"$" + property + "\")")));
|
||||
}
|
||||
|
||||
private void processBodyElement(String property, Map.Entry entry) {
|
||||
processBodyElement(property, getMapKeyReferenceString(property, entry),
|
||||
entry.getValue());
|
||||
}
|
||||
|
||||
private void processBodyElement(String property, Map map) {
|
||||
map.entrySet().forEach(o -> processBodyElement(property, (Map.Entry) o));
|
||||
}
|
||||
|
||||
private void processBodyElement(String property, List list) {
|
||||
Iterator iterator = list.iterator();
|
||||
int index = -1;
|
||||
while (iterator.hasNext()) {
|
||||
Object listElement = iterator.next();
|
||||
index = index + 1;
|
||||
String prop = getPropertyInListString(property, index);
|
||||
processBodyElement(property, prop, listElement);
|
||||
}
|
||||
}
|
||||
|
||||
private String getPropertyInListString(String property, Integer listIndex) {
|
||||
return property + "[" + listIndex + "]";
|
||||
}
|
||||
|
||||
private String getMapKeyReferenceString(String property, Map.Entry entry) {
|
||||
return provideProperJsonPathNotation(property) + "." + entry.getKey();
|
||||
}
|
||||
|
||||
private String provideProperJsonPathNotation(String property) {
|
||||
return property.replaceAll("(get\\(\\\\\")(.*)(\\\\\"\\))", "$2");
|
||||
}
|
||||
|
||||
private String wrappedWithBracketsForDottedProp(String key) {
|
||||
String remindingKey = trailingKey(key);
|
||||
if (remindingKey.contains(".")) {
|
||||
return "['" + remindingKey + "']";
|
||||
}
|
||||
return remindingKey;
|
||||
}
|
||||
|
||||
private String trailingKey(String key) {
|
||||
if (key.startsWith(".")) {
|
||||
return key.substring(1);
|
||||
}
|
||||
return key;
|
||||
}
|
||||
|
||||
private String subtract(String self, String text) {
|
||||
int index = self.indexOf(text);
|
||||
if (index == -1) {
|
||||
return self;
|
||||
}
|
||||
int end = index + text.length();
|
||||
if (self.length() > end) {
|
||||
return self.substring(0, index) + self.substring(end);
|
||||
}
|
||||
return self.substring(0, index);
|
||||
}
|
||||
|
||||
private void simpleTextResponseBodyCheck(SingleContractMetadata metadata,
|
||||
Object convertedResponseBody) {
|
||||
this.blockBuilder.addLineWithEnding(
|
||||
getSimpleResponseBodyString(this.bodyParser.responseAsString()));
|
||||
this.bodyAssertionLineCreator.appendBodyAssertionLine(metadata, "",
|
||||
convertedResponseBody);
|
||||
this.blockBuilder.addEndingIfNotPresent();
|
||||
}
|
||||
|
||||
private String getSimpleResponseBodyString(String responseString) {
|
||||
return "String responseBody = " + responseString
|
||||
+ this.blockBuilder.getLineEnding();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
ContentType outputTestContentType = metadata.getOutputTestContentType();
|
||||
return JSON == outputTestContentType
|
||||
|| mostLikelyJson(outputTestContentType, metadata);
|
||||
}
|
||||
|
||||
private boolean mostLikelyJson(ContentType outputTestContentType,
|
||||
SingleContractMetadata metadata) {
|
||||
return DEFINED == outputTestContentType && metadata.evaluatesToJson();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.FromFileProperty;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
import org.springframework.cloud.contract.verifier.util.ContentType;
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.JSON;
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.XML;
|
||||
|
||||
class GenericTextBodyThen implements Then {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final BodyAssertionLineCreator bodyAssertionLineCreator;
|
||||
|
||||
private final BodyParser bodyParser;
|
||||
|
||||
private final ComparisonBuilder comparisonBuilder;
|
||||
|
||||
GenericTextBodyThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData,
|
||||
BodyParser bodyParser, ComparisonBuilder comparisonBuilder) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.bodyParser = bodyParser;
|
||||
this.comparisonBuilder = comparisonBuilder;
|
||||
this.bodyAssertionLineCreator = new BodyAssertionLineCreator(blockBuilder,
|
||||
metaData, this.bodyParser.byteArrayString(), this.comparisonBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<Then> apply(SingleContractMetadata metadata) {
|
||||
Object convertedResponseBody = this.bodyParser.convertResponseBody(metadata);
|
||||
if (convertedResponseBody instanceof String) {
|
||||
convertedResponseBody = this.bodyParser
|
||||
.escapeForSimpleTextAssertion(convertedResponseBody.toString());
|
||||
}
|
||||
simpleTextResponseBodyCheck(metadata, convertedResponseBody);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void simpleTextResponseBodyCheck(SingleContractMetadata metadata,
|
||||
Object convertedResponseBody) {
|
||||
this.blockBuilder.addLineWithEnding(
|
||||
getSimpleResponseBodyString(this.bodyParser.responseAsString()));
|
||||
this.bodyAssertionLineCreator.appendBodyAssertionLine(metadata, "",
|
||||
convertedResponseBody);
|
||||
this.blockBuilder.addEndingIfNotPresent();
|
||||
}
|
||||
|
||||
private String getSimpleResponseBodyString(String responseString) {
|
||||
return "String responseBody = " + responseString
|
||||
+ this.blockBuilder.getLineEnding();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
ContentType outputTestContentType = metadata.getOutputTestContentType();
|
||||
return outputTestContentType != JSON && outputTestContentType != XML
|
||||
&& this.bodyParser.responseBody(metadata) != null
|
||||
&& !(this.bodyParser.responseBody(metadata)
|
||||
.getServerValue() instanceof FromFileProperty);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* 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 java.util.Optional;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.BodyMatchers;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
import org.springframework.cloud.contract.verifier.util.ContentType;
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentType.XML;
|
||||
|
||||
class GenericXmlBodyThen implements Then {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final BodyParser bodyParser;
|
||||
|
||||
GenericXmlBodyThen(BlockBuilder blockBuilder, BodyParser bodyParser) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.bodyParser = bodyParser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<Then> apply(SingleContractMetadata metadata) {
|
||||
BodyMatchers bodyMatchers = this.bodyParser.responseBodyMatchers(metadata);
|
||||
Object convertedResponseBody = this.bodyParser.convertResponseBody(metadata);
|
||||
XmlBodyVerificationBuilder xmlBodyVerificationBuilder = new XmlBodyVerificationBuilder(
|
||||
metadata.getContract(), Optional.of(this.blockBuilder.getLineEnding()));
|
||||
xmlBodyVerificationBuilder.addXmlResponseBodyCheck(this.blockBuilder,
|
||||
convertedResponseBody, bodyMatchers, this.bodyParser.responseAsString(),
|
||||
true);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
ContentType outputTestContentType = metadata.getOutputTestContentType();
|
||||
return XML == outputTestContentType;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 Given extends MethodVisitor<Given> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.template.TemplateProcessor;
|
||||
|
||||
interface GroovyBodyParser extends BodyParser {
|
||||
|
||||
@Override
|
||||
default String convertUnicodeEscapesIfRequired(String json) {
|
||||
return StringEscapeUtils.unescapeEcmaScript(json);
|
||||
}
|
||||
|
||||
@Override
|
||||
default String postProcessJsonPath(String jsonPath) {
|
||||
if (templateProcessor().containsTemplateEntry(jsonPath)) {
|
||||
return jsonPath;
|
||||
}
|
||||
return jsonPath.replace("$", "\\$");
|
||||
}
|
||||
|
||||
TemplateProcessor templateProcessor();
|
||||
|
||||
@Override
|
||||
default String escape(String text) {
|
||||
return text.replaceAll("\\n", "\\\\n");
|
||||
}
|
||||
|
||||
@Override
|
||||
default String escapeForSimpleTextAssertion(String text) {
|
||||
return escape(text);
|
||||
}
|
||||
|
||||
@Override
|
||||
default String quotedShortText(Object text) {
|
||||
String string = text.toString();
|
||||
if (text instanceof Number) {
|
||||
return string;
|
||||
}
|
||||
else if (string.contains("'") || string.contains("\"")) {
|
||||
return quotedLongText(text);
|
||||
}
|
||||
return "'" + groovyEscapedString(text.toString()) + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
default String quotedEscapedShortText(Object text) {
|
||||
String string = text.toString();
|
||||
if (text instanceof Number) {
|
||||
return string;
|
||||
}
|
||||
else if (string.contains("'") || string.contains("\"")) {
|
||||
return quotedEscapedLongText(text);
|
||||
}
|
||||
return "'" + text.toString() + "'";
|
||||
}
|
||||
|
||||
@Override
|
||||
default String quotedEscapedLongText(Object text) {
|
||||
return "'''" + text.toString() + "'''";
|
||||
}
|
||||
|
||||
@Override
|
||||
default String quotedLongText(Object text) {
|
||||
return "'''" + groovyEscapedString(text) + "'''";
|
||||
}
|
||||
|
||||
default String groovyEscapedString(Object text) {
|
||||
return escape(text.toString()).replaceAll("\\\\\"", "\"");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* 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.verifier.config.ContractVerifierConfigProperties;
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
class GroovyClassMetaData implements ClassMetaData, DefaultClassMetadata {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final BaseClassProvider baseClassProvider = new BaseClassProvider();
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
GroovyClassMetaData(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassMetaData setupLineEnding() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassMetaData setupLabelPrefix() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassMetaData suffix() {
|
||||
String suffix = StringUtils.hasText(
|
||||
this.generatedClassMetaData.configProperties.getNameSuffixForTests())
|
||||
? this.generatedClassMetaData.configProperties
|
||||
.getNameSuffixForTests()
|
||||
: "Spec";
|
||||
if (!this.blockBuilder.endsWith(suffix)) {
|
||||
this.blockBuilder.addAtTheEnd(suffix);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassMetaData modifier() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassMetaData packageDefinition() {
|
||||
this.blockBuilder.addLineWithEnding(
|
||||
"package " + this.generatedClassMetaData.generatedClassData.classPackage);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassMetaData parentClass() {
|
||||
ContractVerifierConfigProperties properties = generatedClassMetaData().configProperties;
|
||||
String includedDirectoryRelativePath = generatedClassMetaData().includedDirectoryRelativePath;
|
||||
String baseClass = baseClassProvider().retrieveBaseClass(properties,
|
||||
includedDirectoryRelativePath);
|
||||
baseClass = StringUtils.hasText(baseClass) ? baseClass : "Specification";
|
||||
int lastIndexOf = baseClass.lastIndexOf(".");
|
||||
if (lastIndexOf > 0) {
|
||||
baseClass = baseClass.substring(lastIndexOf + 1);
|
||||
}
|
||||
blockBuilder().append("extends ").append(baseClass).append(" ");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeneratedClassMetaData generatedClassMetaData() {
|
||||
return this.generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseClassProvider baseClassProvider() {
|
||||
return this.baseClassProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBuilder blockBuilder() {
|
||||
return this.blockBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.SPOCK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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 java.util.regex.Pattern;
|
||||
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
|
||||
interface GroovyComparisonBuilder extends ComparisonBuilder {
|
||||
|
||||
ComparisonBuilder SPOCK_HTTP_INSTANCE = (GroovyComparisonBuilder) () -> SpockRestAssuredBodyParser.INSTANCE;
|
||||
|
||||
ComparisonBuilder JAXRS_HTTP_INSTANCE = (GroovyComparisonBuilder) () -> JaxRsBodyParser.INSTANCE;
|
||||
|
||||
ComparisonBuilder SPOCK_MESSAGING_INSTANCE = (GroovyComparisonBuilder) () -> SpockMessagingBodyParser.INSTANCE;
|
||||
|
||||
@Override
|
||||
default String assertThat(String object) {
|
||||
return object;
|
||||
}
|
||||
|
||||
@Override
|
||||
default String isEqualToUnquoted(String unquoted) {
|
||||
return " == " + unquoted;
|
||||
}
|
||||
|
||||
@Override
|
||||
default String isEqualTo(Number number) {
|
||||
return " == " + number.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
default String matches(String pattern) {
|
||||
return matchesEscaped(bodyParser().quotedShortText(pattern));
|
||||
}
|
||||
|
||||
@Override
|
||||
default String matches(Pattern pattern) {
|
||||
String escapedPattern = StringEscapeUtils.escapeJava(pattern.pattern());
|
||||
return matchesEscaped(escapedPattern);
|
||||
}
|
||||
|
||||
@Override
|
||||
default String matchesEscaped(String pattern) {
|
||||
return " ==~ java.util.regex.Pattern.compile("
|
||||
+ bodyParser().quotedEscapedShortText(pattern) + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
default String isNotNull() {
|
||||
return " != null";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* 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 java.util.regex.Pattern
|
||||
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.internal.Cookie
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Header
|
||||
import org.springframework.cloud.contract.spec.internal.NotToEscapePattern
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
/**
|
||||
* A {@link SpockMethodRequestProcessingBodyBuilder} implementation that uses MockMvc to send requests.
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@PackageScope
|
||||
@TypeChecked
|
||||
class HttpSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProcessingBodyBuilder {
|
||||
|
||||
HttpSpockMethodRequestProcessingBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseCodeBlock(BlockBuilder bb) {
|
||||
bb.addLine("response.statusCode == $response.status.serverValue")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseHeadersBlock(BlockBuilder bb) {
|
||||
response.headers?.executeForEachHeader { Header header ->
|
||||
processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ?
|
||||
header.serverValue :
|
||||
MapConverter.getTestSideValues(header.serverValue))
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseCookiesBlock(BlockBuilder bb) {
|
||||
response.cookies?.executeForEachCookie { Cookie cookie ->
|
||||
processCookieElement(bb, cookie.key, cookie.serverValue instanceof NotToEscapePattern ?
|
||||
cookie.serverValue :
|
||||
MapConverter.getTestSideValues(cookie.serverValue))
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseAsString() {
|
||||
return 'response.body.asString()'
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) {
|
||||
if (value instanceof NotToEscapePattern) {
|
||||
blockBuilder.addLine("response.header('$property') "
|
||||
+
|
||||
"${patternComparison(((NotToEscapePattern) value).serverValue.pattern().replace("\\", "\\\\"))}")
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
processHeaderElement(blockBuilder, property, value.toString())
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, Object value) {
|
||||
if (value instanceof NotToEscapePattern) {
|
||||
blockBuilder.addLine("response.cookie('$key') "
|
||||
+
|
||||
"${patternComparison(((NotToEscapePattern) value).serverValue.pattern().replace("\\", "\\\\"))}")
|
||||
}
|
||||
else {
|
||||
processCookieElement(blockBuilder, key, value.toString())
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number number) {
|
||||
blockBuilder.addLine("response.header('$property') == ${number}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
|
||||
blockBuilder.addLine("${exec.insertValue("response.header(\'$property\')")}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
|
||||
blockBuilder.
|
||||
addLine("response.header('$property') ${convertHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern value) {
|
||||
blockBuilder.
|
||||
addLine("response.header('$property') ${convertHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) {
|
||||
blockBuilder.addLine("response.cookie('$key') != null")
|
||||
blockBuilder.
|
||||
addLine("response.cookie('$key') ${convertCookieComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) {
|
||||
blockBuilder.addLine("response.cookie('$key') != null")
|
||||
blockBuilder.addLine("response.cookie('$key') ${convertCookieComparison(value)}")
|
||||
}
|
||||
|
||||
// #273 - should escape $ for Groovy since it will try to make it a GString
|
||||
@Override
|
||||
protected String postProcessJsonPathCall(String jsonPath) {
|
||||
if (templateProcessor.containsTemplateEntry(jsonPath)) {
|
||||
return jsonPath
|
||||
}
|
||||
return jsonPath.replace('$', '\\$')
|
||||
}
|
||||
}
|
||||
@@ -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 Imports extends Visitor<Imports> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
class ImportsBuilder {
|
||||
|
||||
private final GeneratedTestClassBuilder parentBuilder;
|
||||
|
||||
private final BlockBuilder builder;
|
||||
|
||||
private final GeneratedClassMetaData metaData;
|
||||
|
||||
ImportsBuilder(GeneratedTestClassBuilder generatedTestClassBuilder) {
|
||||
this.parentBuilder = generatedTestClassBuilder;
|
||||
this.builder = generatedTestClassBuilder.blockBuilder;
|
||||
this.metaData = generatedTestClassBuilder.generatedClassMetaData;
|
||||
}
|
||||
|
||||
ImportsBuilder defaultImports() {
|
||||
this.parentBuilder.imports(new DefaultImports(builder, metaData));
|
||||
this.parentBuilder.staticImports(new DefaultStaticImports(builder));
|
||||
return this;
|
||||
}
|
||||
|
||||
ImportsBuilder custom() {
|
||||
this.parentBuilder.imports(new CustomImports(builder, metaData));
|
||||
this.parentBuilder.staticImports(new CustomStaticImports(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
ImportsBuilder json() {
|
||||
this.parentBuilder.imports(new JsonImports(builder, metaData),
|
||||
new JsonPathImports(builder, metaData));
|
||||
this.parentBuilder.staticImports(new DefaultJsonStaticImports(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
ImportsBuilder xml() {
|
||||
this.parentBuilder.imports(new XmlImports(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
ImportsBuilder jUnit4() {
|
||||
this.parentBuilder.imports(new JUnit4Imports(builder, metaData),
|
||||
new JUnit4IgnoreImports(builder, metaData),
|
||||
new JUnit4OrderImports(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
ImportsBuilder jUnit5() {
|
||||
this.parentBuilder.imports(new JUnit5Imports(builder, metaData),
|
||||
new JUnit5IgnoreImports(builder, metaData),
|
||||
new JUnit5OrderImports(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
ImportsBuilder spock() {
|
||||
this.parentBuilder.imports(new SpockImports(builder, metaData),
|
||||
new SpockIgnoreImports(builder, metaData),
|
||||
new SpockOrderImports(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
ImportsBuilder messaging() {
|
||||
this.parentBuilder.imports(new MessagingImports(builder, metaData));
|
||||
this.parentBuilder.staticImports(new MessagingStaticImports(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
ImportsBuilder restAssured() {
|
||||
this.parentBuilder.imports(new MockMvcRestAssuredImports(builder, metaData),
|
||||
new ExplicitRestAssuredImports(builder, metaData),
|
||||
new WebTestClientRestAssuredImports(builder, metaData));
|
||||
this.parentBuilder.staticImports(
|
||||
new MockMvcRestAssuredStaticImports(builder, metaData),
|
||||
new ExplicitRestAssuredStaticImports(builder, metaData),
|
||||
new WebTestClientRestAssured3StaticImports(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
ImportsBuilder jaxRs() {
|
||||
this.parentBuilder.imports(new JaxRsImports(builder, metaData));
|
||||
this.parentBuilder.staticImports(new JaxRsStaticImports(builder, metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
GeneratedTestClassBuilder build() {
|
||||
return this.parentBuilder;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JUnit4IgnoreImports implements Imports {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
JUnit4IgnoreImports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
this.blockBuilder.addLineWithEnding("import org.junit.Ignore");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT
|
||||
&& this.generatedClassMetaData.listOfFiles.stream()
|
||||
.anyMatch(metadata -> metadata.isIgnored()
|
||||
|| metadata.getConvertedContractWithMetadata().stream()
|
||||
.anyMatch(SingleContractMetadata::isIgnored));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JUnit4IgnoreMethodAnnotation implements MethodAnnotations {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] ANNOTATIONS = { "@Ignore" };
|
||||
|
||||
JUnit4IgnoreMethodAnnotation(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<MethodAnnotations> apply(
|
||||
SingleContractMetadata singleContractMetadata) {
|
||||
Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata singleContractMetadata) {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT
|
||||
&& this.generatedClassMetaData.isAnyIgnored();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
|
||||
class JUnit4Imports implements Imports {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] IMPORTS = { "org.junit.Test", "org.junit.Rule" };
|
||||
|
||||
JUnit4Imports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
Arrays.stream(IMPORTS)
|
||||
.forEach(s -> this.blockBuilder.addLineWithEnding("import " + s));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JUnit4MethodAnnotation implements MethodAnnotations {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] ANNOTATIONS = { "@Test" };
|
||||
|
||||
JUnit4MethodAnnotation(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata singleContractMetadata) {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<MethodAnnotations> apply(
|
||||
SingleContractMetadata singleContractMetadata) {
|
||||
Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented);
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
|
||||
class JUnit4OrderClassAnnotation implements ClassAnnotation {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] ANNOTATIONS = {
|
||||
"@FixMethodOrder(MethodSorters.NAME_ASCENDING)" };
|
||||
|
||||
JUnit4OrderClassAnnotation(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassAnnotation call() {
|
||||
Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT
|
||||
&& this.generatedClassMetaData.listOfFiles.stream()
|
||||
.anyMatch(meta -> meta.getOrder() != null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
|
||||
class JUnit4OrderImports implements Imports {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] IMPORTS = { "org.junit.FixMethodOrder",
|
||||
"org.junit.runners.MethodSorters" };
|
||||
|
||||
JUnit4OrderImports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
Arrays.stream(IMPORTS)
|
||||
.forEach(s -> this.blockBuilder.addLineWithEnding("import " + s));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT
|
||||
&& this.generatedClassMetaData.listOfFiles.stream()
|
||||
.anyMatch(meta -> meta.getOrder() != null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JUnit5IgnoreImports implements Imports {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
JUnit5IgnoreImports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
this.blockBuilder.addLineWithEnding("import org.junit.jupiter.api.Disabled");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT5
|
||||
&& this.generatedClassMetaData.listOfFiles.stream()
|
||||
.anyMatch(metadata -> metadata.isIgnored()
|
||||
|| metadata.getConvertedContractWithMetadata().stream()
|
||||
.anyMatch(SingleContractMetadata::isIgnored));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JUnit5IgnoreMethodAnnotation implements MethodAnnotations {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] ANNOTATIONS = { "@Disabled" };
|
||||
|
||||
JUnit5IgnoreMethodAnnotation(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<MethodAnnotations> apply(
|
||||
SingleContractMetadata singleContractMetadata) {
|
||||
Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata singleContractMetadata) {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT5
|
||||
&& this.generatedClassMetaData.isAnyIgnored();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
|
||||
class JUnit5Imports implements Imports {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] IMPORTS = { "org.junit.jupiter.api.Test",
|
||||
"org.junit.jupiter.api.extension.ExtendWith" };
|
||||
|
||||
JUnit5Imports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
Arrays.stream(IMPORTS)
|
||||
.forEach(s -> this.blockBuilder.addLineWithEnding("import " + s));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT5;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JUnit5MethodAnnotation implements MethodAnnotations {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] ANNOTATIONS = { "@Test" };
|
||||
|
||||
JUnit5MethodAnnotation(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<MethodAnnotations> apply(
|
||||
SingleContractMetadata singleContractMetadata) {
|
||||
Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata singleContractMetadata) {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT5;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
|
||||
class JUnit5OrderClassAnnotation implements ClassAnnotation {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] ANNOTATIONS = {
|
||||
"@FixMethodOrder(MethodSorters.NAME_ASCENDING)" };
|
||||
|
||||
JUnit5OrderClassAnnotation(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassAnnotation call() {
|
||||
// Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented);
|
||||
throw new UnsupportedOperationException(
|
||||
"Not implemented yet in JUnit5 - https://github.com/junit-team/junit5/issues/48");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT5
|
||||
&& this.generatedClassMetaData.listOfFiles.stream()
|
||||
.anyMatch(meta -> meta.getOrder() != null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
|
||||
class JUnit5OrderImports implements Imports {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] IMPORTS = { "" };
|
||||
|
||||
JUnit5OrderImports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
// Arrays.stream(IMPORTS)
|
||||
// .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s));
|
||||
throw new UnsupportedOperationException(
|
||||
"Not implemented yet in JUnit5 - https://github.com/junit-team/junit5/issues/48");
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT5
|
||||
&& this.generatedClassMetaData.listOfFiles.stream()
|
||||
.anyMatch(meta -> meta.getOrder() != null);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,292 +0,0 @@
|
||||
/*
|
||||
* 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 java.util.regex.Pattern
|
||||
|
||||
import groovy.json.StringEscapeUtils
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.internal.Cookie
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Header
|
||||
import org.springframework.cloud.contract.spec.internal.Input
|
||||
import org.springframework.cloud.contract.spec.internal.NamedProperty
|
||||
import org.springframework.cloud.contract.spec.internal.NotToEscapePattern
|
||||
import org.springframework.cloud.contract.spec.internal.RegexProperty
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
import static groovy.json.StringEscapeUtils.escapeJava
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT
|
||||
|
||||
/**
|
||||
* Builds a JUnit method for messaging
|
||||
*
|
||||
* Do not change to {@code @CompileStatic} since it's using double dispatch.
|
||||
*
|
||||
* @author Marcin Grzejszczak
|
||||
* @author Jakub Kubrynski, codearte.io
|
||||
* @author Tim Ysewyn
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@PackageScope
|
||||
@TypeChecked
|
||||
class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder {
|
||||
|
||||
JUnitMessagingMethodBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInputString(Input request) {
|
||||
if (request.triggeredBy) {
|
||||
return request.triggeredBy.executionCommand
|
||||
}
|
||||
return "contractVerifierMessaging.send(inputMessage, \"${request.messageFrom.serverValue}\")"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, Object value) {
|
||||
return ""
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, String value) {
|
||||
return ""
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, Pattern value) {
|
||||
return ""
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, ExecutionProperty value) {
|
||||
return ""
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) {
|
||||
if (value.isByte()) {
|
||||
return "assertThat(response.getPayloadAsByteArray()).isEqualTo(" +
|
||||
readBytesFromFileString(value, CommunicationType.RESPONSE) + ")"
|
||||
}
|
||||
return getResponseBodyPropertyComparisonString(property, value.asString())
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
|
||||
blockBuilder.addLine("${exec.insertValue("parsedJson.read('\\\$$property')")}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) {
|
||||
processBodyElement(blockBuilder, property, property + "." + entry.key, entry.value)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
|
||||
blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeader(\"$property\").toString()).${createHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) {
|
||||
blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeader(\"$property\")).isEqualTo(${value});")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) {
|
||||
blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeader(\"$property\").toString()).${createHeaderComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
|
||||
blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();")
|
||||
blockBuilder.
|
||||
addLine("${exec.insertValue("response.getHeader(\"$property\").toString()")};")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, GString value) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseCodeBlock(BlockBuilder bb) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseHeadersBlock(BlockBuilder bb) {
|
||||
bb.addLine("""ContractVerifierMessage response = contractVerifierMessaging.receive(${
|
||||
sentToValue(outputMessage.sentTo.serverValue)
|
||||
});""")
|
||||
bb.addLine("""assertThat(response).isNotNull();""")
|
||||
outputMessage.headers?.executeForEachHeader { Header header ->
|
||||
processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ?
|
||||
header.serverValue :
|
||||
MapConverter.getTestSideValues(header.serverValue))
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseCookiesBlock(BlockBuilder bb) {
|
||||
}
|
||||
|
||||
private String sentToValue(Object sentTo) {
|
||||
if (sentTo instanceof ExecutionProperty) {
|
||||
return ((ExecutionProperty) sentTo).executionCommand
|
||||
}
|
||||
return '"' + sentTo.toString() + '"'
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseAsString() {
|
||||
return 'contractVerifierObjectMapper.writeValueAsString(response.getPayload())'
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String addCommentSignIfRequired(String baseString) {
|
||||
return "// $baseString"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldCommentOutBDDBlocks() {
|
||||
return true
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockBuilder addColonIfRequired(BlockBuilder blockBuilder) {
|
||||
blockBuilder.addAtTheEnd(JUNIT.lineSuffix)
|
||||
return blockBuilder
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<String> lineSuffix() {
|
||||
return Optional.of(JUNIT.lineSuffix)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPropertyInListString(String property, Integer listIndex) {
|
||||
return "$property[$listIndex]" ?: ''
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String convertUnicodeEscapesIfRequired(String json) {
|
||||
return StringEscapeUtils.unescapeJavaScript(json)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSimpleResponseBodyString(String responseString) {
|
||||
return "Object responseBody = ($responseString);"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInputString() {
|
||||
String request = 'ContractVerifierMessage inputMessage = contractVerifierMessaging.create('
|
||||
if (inputMessage.messageBody) {
|
||||
request = "${request}${getBodyAsString()}"
|
||||
}
|
||||
if (inputMessage.messageHeaders) {
|
||||
request = "${request}${indentHeadersString()}"
|
||||
}
|
||||
inputMessage.messageHeaders?.executeForEachHeader { Header header ->
|
||||
request = "${request}${indentedHeaderString(header)}"
|
||||
}
|
||||
return finishIndentation(request)
|
||||
}
|
||||
|
||||
private String indentHeadersString() {
|
||||
return "\t\t\t\t, headers()"
|
||||
}
|
||||
|
||||
private String indentedHeaderString(Header header) {
|
||||
return "\n\t\t\t\t\t\t${getHeaderString(header)}"
|
||||
}
|
||||
|
||||
private String finishIndentation(String text) {
|
||||
return "${text}\n\t\t\t)"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getHeaderString(Header header) {
|
||||
return ".header(${getTestSideValue(header.name)}, ${getTestSideValue(header.serverValue)})"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCookieString(Cookie cookie) {
|
||||
return ""
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBodyString(Object body) {
|
||||
return ""
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMultipartFileParameterContent(String propertyName, NamedProperty propertyValue) {
|
||||
return ""
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getParameterString(Map.Entry<String, Object> parameter) {
|
||||
return ""
|
||||
}
|
||||
|
||||
protected String convertHeaderComparison(String headerValue) {
|
||||
return ""
|
||||
}
|
||||
|
||||
protected String convertHeaderComparison(Pattern headerValue) {
|
||||
return ""
|
||||
}
|
||||
|
||||
protected String convertHeaderComparison(RegexProperty headerValue) {
|
||||
return convertHeaderComparison(headerValue.pattern)
|
||||
}
|
||||
|
||||
protected String createHeaderComparison(Object headerValue) {
|
||||
String escapedHeader = convertUnicodeEscapesIfRequired("$headerValue")
|
||||
return "isEqualTo(\"$escapedHeader\");"
|
||||
}
|
||||
|
||||
protected String createHeaderComparison(Pattern headerValue) {
|
||||
String escapedJavaHeader = escapeJava(headerValue.pattern())
|
||||
return "matches(\"$escapedJavaHeader\");"
|
||||
}
|
||||
}
|
||||
@@ -1,244 +0,0 @@
|
||||
/*
|
||||
* 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 java.util.regex.Pattern
|
||||
|
||||
import groovy.json.StringEscapeUtils
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.internal.Cookie
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Header
|
||||
import org.springframework.cloud.contract.spec.internal.NamedProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Request
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.util.RegexpBuilders
|
||||
|
||||
import static groovy.json.StringEscapeUtils.escapeJava
|
||||
import static org.apache.commons.text.StringEscapeUtils.escapeJava
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT5
|
||||
import static org.springframework.cloud.contract.verifier.util.ContentUtils.getJavaMultipartFileParameterContent
|
||||
|
||||
/**
|
||||
* Root class for JUnit method building
|
||||
*
|
||||
* Do not change to {@code @CompileStatic} since it's using double dispatch.
|
||||
*
|
||||
* @author Jakub Kubrynski, codearte.io
|
||||
* @author Olga Maciaszek-Sharma, codearte.io
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TypeChecked
|
||||
@PackageScope
|
||||
abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder {
|
||||
|
||||
JUnitMethodBodyBuilder(Contract stubDefinition, ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseAsString() {
|
||||
return "response.getBody().asString()"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String addCommentSignIfRequired(String baseString) {
|
||||
return "// $baseString"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean shouldCommentOutBDDBlocks() {
|
||||
return true
|
||||
}
|
||||
|
||||
@Override
|
||||
protected BlockBuilder addColonIfRequired(BlockBuilder blockBuilder) {
|
||||
blockBuilder.addAtTheEnd(JUNIT.lineSuffix)
|
||||
return blockBuilder
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<String> lineSuffix() {
|
||||
return Optional.of(JUNIT5.lineSuffix)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, String value) {
|
||||
return "assertThat(responseBody${property}).isEqualTo(\"${value}\")"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, Object value) {
|
||||
return getResponseBodyPropertyComparisonString(property, value as String)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, Pattern value) {
|
||||
return "assertThat(responseBody${property}).${createBodyComparison(value)}"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, ExecutionProperty value) {
|
||||
return value.insertValue("responseBody${property}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
|
||||
blockBuilder.addLine("${exec.insertValue("parsedJson.read(\"\$$property\")")};")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getPropertyInListString(String property, Integer listIndex) {
|
||||
return "${property}[$listIndex]" ?: ''
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String convertUnicodeEscapesIfRequired(String json) {
|
||||
String unescapedJson = StringEscapeUtils.unescapeJavaScript(json)
|
||||
return escapeJava(unescapedJson)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) {
|
||||
processBodyElement(blockBuilder, property,
|
||||
getMapKeyReferenceString(property, entry), entry.value)
|
||||
}
|
||||
|
||||
private String getMapKeyReferenceString(String property, Map.Entry entry) {
|
||||
return provideProperJsonPathNotation(property) + "." + entry.key
|
||||
}
|
||||
|
||||
private String provideProperJsonPathNotation(String property) {
|
||||
return property.replaceAll('(get\\(\\\\")(.*)(\\\\"\\))', '$2')
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) {
|
||||
if (value.isByte()) {
|
||||
return "assertThat(response.getBody().asByteArray()).isEqualTo(" +
|
||||
readBytesFromFileString(value, CommunicationType.RESPONSE) + ")"
|
||||
}
|
||||
return getResponseBodyPropertyComparisonString(property, value.asString())
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getSimpleResponseBodyString(String responseString) {
|
||||
return "String responseBody = $responseString;"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInputString(Request request) {
|
||||
return "${returnedResponseType()} response = given().spec(request)"
|
||||
}
|
||||
|
||||
protected String returnedResponseType() {
|
||||
return "ResponseOptions"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getInputString() {
|
||||
return "${returnedRequestType()} request = given()"
|
||||
}
|
||||
|
||||
protected String returnedRequestType() {
|
||||
return "MockMvcRequestSpecification"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getHeaderString(Header header) {
|
||||
return ".header(${getTestSideForNonBodyValue(header.name)}, ${getTestSideForNonBodyValue(header.serverValue)})"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getCookieString(Cookie cookie) {
|
||||
return ".cookie(${getTestSideForNonBodyValue(cookie.key)}, ${getTestSideForNonBodyValue(cookie.serverValue)})"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getBodyString(Object body) {
|
||||
String value
|
||||
if (body instanceof ExecutionProperty) {
|
||||
value = body.toString()
|
||||
}
|
||||
else if (body instanceof FromFileProperty) {
|
||||
FromFileProperty fileProperty = (FromFileProperty) body
|
||||
value = fileProperty.isByte() ?
|
||||
readBytesFromFileString(fileProperty, CommunicationType.REQUEST) :
|
||||
readStringFromFileString(fileProperty, CommunicationType.REQUEST)
|
||||
}
|
||||
else {
|
||||
String escaped = escapeRequestSpecialChars(body.toString())
|
||||
value = "\"$escaped\""
|
||||
}
|
||||
return ".body($value)"
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getMultipartFileParameterContent(String propertyName, NamedProperty propertyValue) {
|
||||
return getJavaMultipartFileParameterContent(propertyName, propertyValue, { FromFileProperty fileProp ->
|
||||
readBytesFromFileString(fileProp, CommunicationType.REQUEST)
|
||||
})
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getParameterString(Map.Entry<String, Object> parameter) {
|
||||
return """.param("${escapeJava(parameter.key)}", "${
|
||||
escapeJava(parameter.value as String)
|
||||
}")"""
|
||||
}
|
||||
|
||||
protected String createHeaderComparison(Object headerValue) {
|
||||
String escapedHeader = convertUnicodeEscapesIfRequired("$headerValue")
|
||||
return "isEqualTo(\"$escapedHeader\");"
|
||||
}
|
||||
|
||||
protected String createHeaderComparison(Pattern headerValue) {
|
||||
return createMatchesMethod(escapeJava(headerValue.pattern())) + ";"
|
||||
}
|
||||
|
||||
protected String createBodyComparison(Pattern bodyValue) {
|
||||
String patternAsString = bodyValue.pattern()
|
||||
return createMatchesMethod(RegexpBuilders.
|
||||
buildGStringRegexpForTestSide(patternAsString)) + ";"
|
||||
}
|
||||
|
||||
protected String createCookieComparison(Object cookieValue) {
|
||||
String escapedCookie = convertUnicodeEscapesIfRequired("$cookieValue")
|
||||
return "isEqualTo(\"$escapedCookie\");"
|
||||
}
|
||||
|
||||
protected String createCookieComparison(Pattern cookieValue) {
|
||||
return createMatchesMethod(escapeJava(cookieValue.pattern())) + ";"
|
||||
}
|
||||
|
||||
private String buildEscapedMatchesMethod(Pattern escapedValue) {
|
||||
String escapedHeader = convertUnicodeEscapesIfRequired("$escapedValue")
|
||||
return createMatchesMethod(escapedHeader)
|
||||
}
|
||||
|
||||
protected String createMatchesMethod(String pattern) {
|
||||
return "matches(\"$pattern\")"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JUnitMethodMetadata implements MethodMetadata {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData metaData;
|
||||
|
||||
private final NameProvider nameProvider = new NameProvider();
|
||||
|
||||
JUnitMethodMetadata(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.metaData = metaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodMetadata name(SingleContractMetadata metaData) {
|
||||
this.blockBuilder.addAtTheEnd(this.nameProvider.methodName(metaData));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodMetadata modifier() {
|
||||
this.blockBuilder.addIndented("public");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodMetadata returnType() {
|
||||
this.blockBuilder.append("void");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.metaData.configProperties.getTestFramework() != TestFramework.SPOCK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
class JavaClassMetaData implements ClassMetaData, DefaultClassMetadata {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final BaseClassProvider baseClassProvider = new BaseClassProvider();
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
JavaClassMetaData(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassMetaData modifier() {
|
||||
this.blockBuilder.append("public");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassMetaData suffix() {
|
||||
String suffix = StringUtils.hasText(
|
||||
this.generatedClassMetaData.configProperties.getNameSuffixForTests())
|
||||
? this.generatedClassMetaData.configProperties
|
||||
.getNameSuffixForTests()
|
||||
: "Test";
|
||||
if (!this.blockBuilder.endsWith(suffix)) {
|
||||
this.blockBuilder.addAtTheEnd(suffix);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassMetaData setupLineEnding() {
|
||||
this.blockBuilder.setupLineEnding(";");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassMetaData setupLabelPrefix() {
|
||||
this.blockBuilder.setupLabelPrefix("// ");
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GeneratedClassMetaData generatedClassMetaData() {
|
||||
return this.generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BaseClassProvider baseClassProvider() {
|
||||
return this.baseClassProvider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBuilder blockBuilder() {
|
||||
return this.blockBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClassMetaData parentClass() {
|
||||
String baseClass = fqnBaseClass();
|
||||
if (StringUtils.hasText(baseClass)) {
|
||||
int lastIndexOf = baseClass.lastIndexOf(".");
|
||||
if (lastIndexOf > 0) {
|
||||
baseClass = baseClass.substring(lastIndexOf + 1);
|
||||
}
|
||||
blockBuilder().append("extends ").append(baseClass).append(" ");
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT
|
||||
|| this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() == TestFramework.JUNIT5;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JavaJaxRsThen extends JaxRsThen {
|
||||
|
||||
private final GeneratedClassMetaData metaData;
|
||||
|
||||
JavaJaxRsThen(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
super(blockBuilder, generatedClassMetaData, JaxRsBodyParser.INSTANCE,
|
||||
ComparisonBuilder.JAVA_HTTP_INSTANCE);
|
||||
this.metaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata singleContractMetadata) {
|
||||
return super.accept(singleContractMetadata) && this.metaData.configProperties
|
||||
.getTestFramework() != TestFramework.SPOCK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JavaJaxRsWhen extends JaxRsWhen {
|
||||
|
||||
private final GeneratedClassMetaData metaData;
|
||||
|
||||
JavaJaxRsWhen(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
super(blockBuilder, generatedClassMetaData, JaxRsBodyParser.INSTANCE);
|
||||
this.metaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata singleContractMetadata) {
|
||||
return super.accept(singleContractMetadata) && this.metaData.configProperties
|
||||
.getTestFramework() != TestFramework.SPOCK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* 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 JavaMessagingBodyParser extends MessagingBodyParser {
|
||||
|
||||
BodyParser INSTANCE = new JavaMessagingBodyParser() {
|
||||
};
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JavaMessagingGiven extends MessagingGiven {
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
JavaMessagingGiven(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
super(blockBuilder, generatedClassMetaData, JavaMessagingBodyParser.INSTANCE);
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return super.accept(metadata) && this.generatedClassMetaData.configProperties
|
||||
.getTestFramework() != TestFramework.SPOCK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JavaMessagingWithBodyThen extends MessagingWithBodyThen {
|
||||
|
||||
private final GeneratedClassMetaData metaData;
|
||||
|
||||
JavaMessagingWithBodyThen(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
super(blockBuilder, generatedClassMetaData,
|
||||
ComparisonBuilder.JAVA_MESSAGING_INSTANCE);
|
||||
this.metaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata singleContractMetadata) {
|
||||
return super.accept(singleContractMetadata) && this.metaData.configProperties
|
||||
.getTestFramework() != TestFramework.SPOCK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JavaRestAssuredGiven extends RestAssuredGiven {
|
||||
|
||||
private final GeneratedClassMetaData metaData;
|
||||
|
||||
JavaRestAssuredGiven(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
super(blockBuilder, generatedClassMetaData, RestAssuredBodyParser.INSTANCE);
|
||||
this.metaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata singleContractMetadata) {
|
||||
return super.accept(singleContractMetadata) && this.metaData.configProperties
|
||||
.getTestFramework() != TestFramework.SPOCK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JavaRestAssuredThen extends RestAssuredThen {
|
||||
|
||||
private final GeneratedClassMetaData metaData;
|
||||
|
||||
JavaRestAssuredThen(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
super(blockBuilder, generatedClassMetaData, RestAssuredBodyParser.INSTANCE,
|
||||
ComparisonBuilder.JAVA_HTTP_INSTANCE);
|
||||
this.metaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata singleContractMetadata) {
|
||||
return super.accept(singleContractMetadata) && this.metaData.configProperties
|
||||
.getTestFramework() != TestFramework.SPOCK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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.verifier.config.TestFramework;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JavaRestAssuredWhen extends RestAssuredWhen {
|
||||
|
||||
private final GeneratedClassMetaData metaData;
|
||||
|
||||
JavaRestAssuredWhen(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
super(blockBuilder, generatedClassMetaData, RestAssuredBodyParser.INSTANCE);
|
||||
this.metaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata singleContractMetadata) {
|
||||
return super.accept(singleContractMetadata) && this.metaData.configProperties
|
||||
.getTestFramework() != TestFramework.SPOCK;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,232 +0,0 @@
|
||||
/*
|
||||
* 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 java.lang.invoke.MethodHandles
|
||||
|
||||
import groovy.transform.Canonical
|
||||
import groovy.transform.CompileStatic
|
||||
import groovy.transform.EqualsAndHashCode
|
||||
import groovy.transform.PackageScope
|
||||
import org.apache.commons.logging.Log
|
||||
import org.apache.commons.logging.LogFactory
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.verifier.builder.imports.HttpImportProvider
|
||||
import org.springframework.cloud.contract.verifier.builder.imports.MessagingImportProvider
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.builder.imports.BaseImportProvider.getImports
|
||||
import static org.springframework.cloud.contract.verifier.builder.imports.BaseImportProvider.getRuleImport
|
||||
import static org.springframework.cloud.contract.verifier.builder.imports.BaseImportProvider.getStaticImports
|
||||
import static org.springframework.cloud.contract.verifier.util.NamesUtil.capitalize
|
||||
|
||||
/**
|
||||
* Builds a single test for the given {@link ContractVerifierConfigProperties properties}
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
@CompileStatic
|
||||
class JavaTestGenerator implements SingleTestGenerator {
|
||||
|
||||
private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass())
|
||||
|
||||
private static final String JSON_ASSERT_STATIC_IMPORT = 'com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson'
|
||||
private static final String JSON_ASSERT_CLASS = 'com.toomuchcoding.jsonassert.JsonAssertion'
|
||||
@Deprecated
|
||||
// TODO: Remove in next major
|
||||
private static final String REST_ASSURED_2_0_CLASS = 'com.jayway.restassured.RestAssured'
|
||||
|
||||
@PackageScope
|
||||
ClassPresenceChecker checker = new ClassPresenceChecker()
|
||||
|
||||
@Override
|
||||
String buildClass(ContractVerifierConfigProperties configProperties, Collection<ContractMetadata> listOfFiles, String includedDirectoryRelativePath, GeneratedClassData generatedClassData) {
|
||||
String className = generatedClassData.className
|
||||
String classPackage = generatedClassData.classPackage
|
||||
ClassBuilder clazz = ClassBuilder.createClass(
|
||||
capitalize(className), classPackage, configProperties, includedDirectoryRelativePath)
|
||||
if (configProperties.imports) {
|
||||
configProperties.imports.each { String it ->
|
||||
clazz.addImport(it)
|
||||
}
|
||||
}
|
||||
if (configProperties.staticImports) {
|
||||
configProperties.staticImports.each { String it ->
|
||||
clazz.addStaticImport(it)
|
||||
}
|
||||
}
|
||||
if (isScenarioClass(listOfFiles)) {
|
||||
clazz.addImports(configProperties.testFramework.getOrderAnnotationImports())
|
||||
clazz.addClassLevelAnnotation(configProperties.testFramework.
|
||||
getOrderAnnotation())
|
||||
}
|
||||
// FIXME: change during Hoxton refactoring: we should only add either Json or Xml imports and not both
|
||||
addJsonPathRelatedImports(clazz)
|
||||
addXPathRelatedImports(clazz)
|
||||
processContractFiles(listOfFiles, configProperties, clazz, generatedClassData)
|
||||
return clazz.build()
|
||||
}
|
||||
|
||||
@Override
|
||||
String buildClass(ContractVerifierConfigProperties configProperties, Collection<ContractMetadata> listOfFiles, String className, String classPackage, String includedDirectoryRelativePath) {
|
||||
return buildClass(configProperties, listOfFiles, includedDirectoryRelativePath, new GeneratedClassData(className, classPackage, null))
|
||||
}
|
||||
|
||||
private void processContractFiles(Collection<ContractMetadata> listOfFiles, ContractVerifierConfigProperties configProperties, ClassBuilder clazz, GeneratedClassData generatedClassData) {
|
||||
Map<ParsedDsl, TestType> contracts = mapContractsToTheirTestTypes(listOfFiles)
|
||||
boolean conditionalImportsAdded = false
|
||||
boolean toIgnore = listOfFiles.find { it.ignored }
|
||||
contracts.each { ParsedDsl key, TestType value ->
|
||||
if (!conditionalImportsAdded) {
|
||||
clazz.addImports(getImports(configProperties.testFramework))
|
||||
clazz.addStaticImports(getStaticImports(configProperties.testFramework))
|
||||
if (contracts.values().contains(TestType.HTTP)) {
|
||||
addHttpRelatedEntries(clazz, configProperties)
|
||||
}
|
||||
if (configProperties.ruleClassForTests) {
|
||||
addRule(configProperties, clazz)
|
||||
}
|
||||
if (contracts.values().contains(TestType.MESSAGING)) {
|
||||
addMessagingRelatedEntries(clazz)
|
||||
}
|
||||
conditionalImportsAdded = true
|
||||
}
|
||||
toIgnore = toIgnore ? true : key.groovyDsl.ignored
|
||||
clazz.addMethod(MethodBuilder.createTestMethod(key.contract, key.stubsFile,
|
||||
key.groovyDsl, configProperties, generatedClassData))
|
||||
}
|
||||
|
||||
if (toIgnore) {
|
||||
clazz.addImport(configProperties.testFramework.getIgnoreClass())
|
||||
}
|
||||
}
|
||||
|
||||
private void addRule(ContractVerifierConfigProperties configProperties, ClassBuilder clazz) {
|
||||
clazz.addImport(getRuleImport(configProperties.testFramework))
|
||||
if (configProperties.testFramework.annotationLevelRules()) {
|
||||
clazz.addClassLevelAnnotation(configProperties.testFramework
|
||||
.getRuleAnnotation(configProperties.ruleClassForTests))
|
||||
}
|
||||
else {
|
||||
clazz.addRule(configProperties.ruleClassForTests)
|
||||
}
|
||||
}
|
||||
|
||||
private void addHttpRelatedEntries(ClassBuilder clazz, ContractVerifierConfigProperties configProperties) {
|
||||
HttpImportProvider httpImportProvider = new HttpImportProvider(
|
||||
getRestAssuredPackage())
|
||||
clazz.addImports(httpImportProvider.
|
||||
getImports(configProperties.testFramework, configProperties.testMode))
|
||||
clazz.addStaticImports(httpImportProvider.
|
||||
getStaticImports(configProperties.testFramework, configProperties.testMode))
|
||||
}
|
||||
|
||||
// TODO for 2.2: leave only RestAssured 3
|
||||
private String getRestAssuredPackage() {
|
||||
boolean restAssured2Present = this.checker.isClassPresent(REST_ASSURED_2_0_CLASS)
|
||||
String restAssuredPackage = restAssured2Present ? 'com.jayway.restassured' : 'io.restassured'
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Rest Assured version 2.x found [${restAssured2Present}]")
|
||||
}
|
||||
return restAssuredPackage
|
||||
}
|
||||
|
||||
@Override
|
||||
String fileExtension(ContractVerifierConfigProperties properties) {
|
||||
return properties.testFramework.classExtension
|
||||
}
|
||||
|
||||
private Map<ParsedDsl, TestType> mapContractsToTheirTestTypes(Collection<ContractMetadata> listOfFiles) {
|
||||
Map<ParsedDsl, TestType> dsls = [:]
|
||||
listOfFiles.each { ContractMetadata metadata ->
|
||||
File stubsFile = metadata.path.toFile()
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("Stub content from file [${stubsFile.text}]")
|
||||
}
|
||||
Collection<Contract> stubContents = metadata.convertedContract
|
||||
Map<ParsedDsl, TestType> entries = stubContents.
|
||||
collectEntries { Contract stubContent ->
|
||||
TestType testType = (stubContent.input || stubContent.outputMessage) ? TestType.MESSAGING : TestType.HTTP
|
||||
return [(new ParsedDsl(metadata, stubContent, stubsFile)): testType]
|
||||
}
|
||||
dsls.putAll(entries)
|
||||
}
|
||||
return dsls
|
||||
}
|
||||
|
||||
@Canonical
|
||||
@EqualsAndHashCode(includeFields = true)
|
||||
@CompileStatic
|
||||
private static class ParsedDsl {
|
||||
ContractMetadata contract
|
||||
Contract groovyDsl
|
||||
File stubsFile
|
||||
}
|
||||
|
||||
private static enum TestType {
|
||||
MESSAGING, HTTP
|
||||
}
|
||||
|
||||
private boolean isScenarioClass(Collection<ContractMetadata> listOfFiles) {
|
||||
return listOfFiles.find({ it.order != null }) != null
|
||||
}
|
||||
|
||||
private void addJsonPathRelatedImports(ClassBuilder clazz) {
|
||||
clazz.addImports(['com.jayway.jsonpath.DocumentContext',
|
||||
'com.jayway.jsonpath.JsonPath',
|
||||
])
|
||||
if (this.checker.isClassPresent(JSON_ASSERT_CLASS)) {
|
||||
clazz.addStaticImport(JSON_ASSERT_STATIC_IMPORT)
|
||||
}
|
||||
}
|
||||
|
||||
private void addXPathRelatedImports(ClassBuilder clazz) {
|
||||
clazz.addImports(['javax.xml.parsers.DocumentBuilder',
|
||||
'javax.xml.parsers.DocumentBuilderFactory',
|
||||
'org.w3c.dom.Document',
|
||||
'org.xml.sax.InputSource',
|
||||
'java.io.StringReader'])
|
||||
}
|
||||
|
||||
private void addMessagingRelatedEntries(ClassBuilder clazz) {
|
||||
clazz.addField(['@Inject ContractVerifierMessaging contractVerifierMessaging',
|
||||
'@Inject ContractVerifierObjectMapper contractVerifierObjectMapper'
|
||||
])
|
||||
clazz.addImports(MessagingImportProvider.getImports())
|
||||
clazz.addStaticImports(MessagingImportProvider.getStaticImports())
|
||||
}
|
||||
}
|
||||
|
||||
class ClassPresenceChecker {
|
||||
|
||||
private static final Log log = LogFactory.getLog(ClassPresenceChecker)
|
||||
|
||||
boolean isClassPresent(String className) {
|
||||
try {
|
||||
Class.forName(className)
|
||||
return true
|
||||
}
|
||||
catch (ClassNotFoundException ex) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("[${className}] is not present on classpath. Will not add a static import.")
|
||||
}
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
/*
|
||||
* 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 java.util.Collection;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties;
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata;
|
||||
|
||||
/**
|
||||
* Builds a single test for the given {@link ContractVerifierConfigProperties properties}
|
||||
*
|
||||
* @since 1.1.0
|
||||
*/
|
||||
public class JavaTestGenerator implements SingleTestGenerator {
|
||||
|
||||
private static final Log log = LogFactory.getLog(JavaTestGenerator.class);
|
||||
|
||||
@Override
|
||||
public String buildClass(ContractVerifierConfigProperties properties,
|
||||
Collection<ContractMetadata> listOfFiles, String className,
|
||||
String classPackage, String includedDirectoryRelativePath) {
|
||||
throw new UnsupportedOperationException("Deprecated method");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildClass(ContractVerifierConfigProperties properties,
|
||||
Collection<ContractMetadata> listOfFiles,
|
||||
String includedDirectoryRelativePath, GeneratedClassData generatedClassData) {
|
||||
BlockBuilder builder = new BlockBuilder("\t");
|
||||
GeneratedClassMetaData metaData = new GeneratedClassMetaData(properties,
|
||||
listOfFiles, includedDirectoryRelativePath, generatedClassData);
|
||||
return classAsString(builder, metaData);
|
||||
}
|
||||
|
||||
private String classAsString(BlockBuilder builder, GeneratedClassMetaData metaData) {
|
||||
SingleMethodBuilder methodBuilder = singleMethodBuilder(builder, metaData);
|
||||
ClassBodyBuilder bodyBuilder = classBodyBuilder(builder, metaData, methodBuilder);
|
||||
GeneratedTestClass generatedTestClass = generatedTestClass(builder, metaData,
|
||||
bodyBuilder);
|
||||
return generatedTestClass.asClassString();
|
||||
}
|
||||
|
||||
GeneratedTestClass generatedTestClass(BlockBuilder builder,
|
||||
GeneratedClassMetaData metaData, ClassBodyBuilder bodyBuilder) {
|
||||
// @formatter:off
|
||||
return GeneratedTestClassBuilder.builder(builder, metaData)
|
||||
.classBodyBuilder(bodyBuilder)
|
||||
.metaData()
|
||||
.java()
|
||||
.groovy()
|
||||
.build()
|
||||
.imports()
|
||||
.defaultImports()
|
||||
.custom()
|
||||
.json()
|
||||
.jUnit4()
|
||||
.jUnit5()
|
||||
.spock()
|
||||
.xml()
|
||||
.messaging()
|
||||
.restAssured()
|
||||
.jaxRs()
|
||||
.build()
|
||||
.classAnnotations()
|
||||
.jUnit4()
|
||||
.jUnit5()
|
||||
.spock()
|
||||
.build()
|
||||
.build();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
ClassBodyBuilder classBodyBuilder(BlockBuilder builder,
|
||||
GeneratedClassMetaData metaData, SingleMethodBuilder methodBuilder) {
|
||||
// @formatter:off
|
||||
return ClassBodyBuilder.builder(builder, metaData)
|
||||
.field()
|
||||
.messaging()
|
||||
.build()
|
||||
.methodBuilder(methodBuilder);
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
SingleMethodBuilder singleMethodBuilder(BlockBuilder builder,
|
||||
GeneratedClassMetaData metaData) {
|
||||
// @formatter:off
|
||||
return SingleMethodBuilder.builder(builder, metaData)
|
||||
.methodAnnotation()
|
||||
.jUnit4()
|
||||
.jUnit5()
|
||||
.spock()
|
||||
.build()
|
||||
.methodMetadata()
|
||||
.jUnit()
|
||||
.spock()
|
||||
.build()
|
||||
.restAssured()
|
||||
.jaxRs()
|
||||
.messaging();
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
@Override
|
||||
public String fileExtension(ContractVerifierConfigProperties properties) {
|
||||
return properties.getTestFramework().getClassExtension();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* 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.verifier.config.TestMode;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
interface JaxRsAcceptor {
|
||||
|
||||
default boolean acceptType(GeneratedClassMetaData generatedClassMetaData,
|
||||
SingleContractMetadata singleContractMetadata) {
|
||||
return generatedClassMetaData.configProperties
|
||||
.getTestMode() == TestMode.JAXRSCLIENT && singleContractMetadata.isHttp();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* 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 JaxRsBodyParser extends BodyParser {
|
||||
|
||||
JaxRsBodyParser INSTANCE = new JaxRsBodyParser() {
|
||||
};
|
||||
|
||||
default String readEntity() {
|
||||
return "response.readEntity(String.class)";
|
||||
}
|
||||
|
||||
default String responseAsString() {
|
||||
return "responseAsString";
|
||||
}
|
||||
|
||||
default String byteArrayString() {
|
||||
return "response.readEntity(byte[].class)";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
/*
|
||||
* 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 java.util.regex.Pattern
|
||||
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.internal.Cookie
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Header
|
||||
import org.springframework.cloud.contract.spec.internal.NotToEscapePattern
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameter
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameters
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT
|
||||
|
||||
/**
|
||||
* JaxRs implementation of the {@link JUnitMethodBodyBuilder}. Knows how to build
|
||||
* a test method for JaxRs.
|
||||
*
|
||||
* Do not change to {@code @CompileStatic} since it's using double dispatch.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma, codearte.io
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@TypeChecked
|
||||
@PackageScope
|
||||
class JaxRsClientJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder {
|
||||
|
||||
JaxRsClientJUnitMethodBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void given(BlockBuilder bb) {}
|
||||
|
||||
@Override
|
||||
protected void givenBlock(BlockBuilder bb) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void when(BlockBuilder bb) {
|
||||
bb.addLine("Response response = webTarget")
|
||||
bb.indent()
|
||||
|
||||
appendUrlPathAndQueryParameters(bb)
|
||||
appendRequestWithRequiredResponseContentType(bb)
|
||||
appendHeaders(bb)
|
||||
appendCookies(bb)
|
||||
appendMethodAndBody(bb)
|
||||
bb.addAtTheEnd(JUNIT.lineSuffix)
|
||||
|
||||
bb.unindent()
|
||||
|
||||
bb.addEmptyLine()
|
||||
if (expectsResponseBody()) {
|
||||
bb.addLine("String responseAsString = response.readEntity(String.class);")
|
||||
}
|
||||
}
|
||||
|
||||
protected void appendUrlPathAndQueryParameters(BlockBuilder bb) {
|
||||
if (request.url) {
|
||||
bb.addLine(".path(${concreteUrl(request.url)})")
|
||||
appendQueryParams(request.url.queryParameters, bb)
|
||||
}
|
||||
else if (request.urlPath) {
|
||||
bb.addLine(".path(${concreteUrl(request.urlPath)})")
|
||||
appendQueryParams(request.urlPath.queryParameters, bb)
|
||||
}
|
||||
}
|
||||
|
||||
protected String concreteUrl(DslProperty url) {
|
||||
Object testSideUrl = MapConverter.getTestSideValues(url)
|
||||
if (!(testSideUrl instanceof ExecutionProperty)) {
|
||||
return '"' + testSideUrl.toString() + '"'
|
||||
}
|
||||
return testSideUrl.toString()
|
||||
}
|
||||
|
||||
private void appendQueryParams(QueryParameters queryParameters, BlockBuilder bb) {
|
||||
if (!queryParameters?.parameters) {
|
||||
return
|
||||
}
|
||||
queryParameters.parameters.findAll(this.&allowedQueryParameter).
|
||||
each { QueryParameter param ->
|
||||
bb.addLine(".queryParam(\"$param.name\", \"${resolveParamValue(param).toString()}\")")
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) {
|
||||
if (value.isByte()) {
|
||||
return "assertThat(response.readEntity(byte[].class)).isEqualTo(" +
|
||||
readBytesFromFileString(value, CommunicationType.RESPONSE) + ")"
|
||||
}
|
||||
return getResponseBodyPropertyComparisonString(property, value.asString())
|
||||
}
|
||||
|
||||
protected void appendMethodAndBody(BlockBuilder bb) {
|
||||
String method = request.method.serverValue.toString().toLowerCase()
|
||||
if (request.body) {
|
||||
String contentType =
|
||||
getHeader('Content-Type') ?: getRequestContentType().mimeType
|
||||
Object body = request.body.serverValue
|
||||
String value
|
||||
if (body instanceof ExecutionProperty) {
|
||||
value = body.toString()
|
||||
}
|
||||
else if (body instanceof FromFileProperty) {
|
||||
FromFileProperty fileProperty = (FromFileProperty) body
|
||||
value = fileProperty.isByte() ?
|
||||
readBytesFromFileString(fileProperty, CommunicationType.REQUEST) :
|
||||
readStringFromFileString(fileProperty, CommunicationType.REQUEST)
|
||||
}
|
||||
else {
|
||||
value = "\"${getBodyAsString()}\""
|
||||
}
|
||||
bb.addLine(".method(\"${method.toUpperCase()}\", entity(${value}, \"$contentType\"))")
|
||||
}
|
||||
else {
|
||||
bb.addLine(".method(\"${method.toUpperCase()}\")")
|
||||
}
|
||||
}
|
||||
|
||||
protected appendHeaders(BlockBuilder bb) {
|
||||
request.headers?.executeForEachHeader { Header header ->
|
||||
if (headerOfAbsentType(header)) {
|
||||
return
|
||||
}
|
||||
if (header.name == 'Content-Type' || header.name == 'Accept') {
|
||||
return
|
||||
}
|
||||
bb.addLine(".header(\"${header.name}\", ${quotedAndEscaped(header.serverValue as String)})")
|
||||
}
|
||||
}
|
||||
|
||||
protected appendCookies(BlockBuilder bb) {
|
||||
request.cookies?.executeForEachCookie { Cookie cookie ->
|
||||
if (cookieOfAbsentType(cookie)) {
|
||||
return
|
||||
}
|
||||
|
||||
bb.addLine(".cookie(\"${cookie.key}\", ${quotedAndEscaped(cookie.serverValue as String)})")
|
||||
}
|
||||
}
|
||||
|
||||
protected void appendRequestWithRequiredResponseContentType(BlockBuilder bb) {
|
||||
String acceptHeader = getHeader("Accept")
|
||||
if (acceptHeader) {
|
||||
bb.addLine(".request(\"$acceptHeader\")")
|
||||
}
|
||||
else {
|
||||
bb.addLine(".request()")
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseCodeBlock(BlockBuilder bb) {
|
||||
bb.addLine("assertThat(response.getStatus()).isEqualTo($response.status.serverValue);")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseHeadersBlock(BlockBuilder bb) {
|
||||
response.headers?.executeForEachHeader { Header header ->
|
||||
processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ?
|
||||
header.serverValue :
|
||||
MapConverter.getTestSideValues(header.serverValue))
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseCookiesBlock(BlockBuilder bb) {
|
||||
response.cookies?.executeForEachCookie { Cookie cookie ->
|
||||
processCookieElement(bb, cookie.key, cookie.serverValue instanceof NotToEscapePattern ?
|
||||
cookie.serverValue :
|
||||
MapConverter.getTestSideValues(cookie.serverValue))
|
||||
}
|
||||
}
|
||||
|
||||
protected String getHeader(String name) {
|
||||
return request.headers?.entries?.find { it.name == name }?.serverValue
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseAsString() {
|
||||
return 'responseAsString'
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) {
|
||||
if (value instanceof NotToEscapePattern) {
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(((NotToEscapePattern) value).serverValue)}")
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
processHeaderElement(blockBuilder, property, value.toString())
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) {
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeaderString(\"$property\")).isEqualTo(${value});")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) {
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
|
||||
blockBuilder.
|
||||
addLine("${exec.insertValue("response.getHeaderString(\"$property\")")};")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) {
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getCookies().get(\"$key\")).isNotNull();")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getCookies().get(\"$key\").getValue()).${createCookieComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) {
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getCookies().get(\"$key\")).isNotNull();")
|
||||
blockBuilder.
|
||||
addLine("assertThat(response.getCookies().get(\"$key\").getValue()).${createCookieComparison(value)}")
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
/*
|
||||
* 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 java.util.regex.Pattern
|
||||
|
||||
import groovy.transform.PackageScope
|
||||
import groovy.transform.TypeChecked
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.spec.internal.Cookie
|
||||
import org.springframework.cloud.contract.spec.internal.DslProperty
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty
|
||||
import org.springframework.cloud.contract.spec.internal.Header
|
||||
import org.springframework.cloud.contract.spec.internal.NotToEscapePattern
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameter
|
||||
import org.springframework.cloud.contract.spec.internal.QueryParameters
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter
|
||||
|
||||
/**
|
||||
* Knows how to build a Spock test method for JaxRs.
|
||||
*
|
||||
* Do not change to {@code @CompileStatic} since it's using double dispatch.
|
||||
*
|
||||
* @author Olga Maciaszek-Sharma, codearte.io
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@PackageScope
|
||||
@TypeChecked
|
||||
class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProcessingBodyBuilder {
|
||||
|
||||
JaxRsClientSpockMethodRequestProcessingBodyBuilder(Contract stubDefinition,
|
||||
ContractVerifierConfigProperties configProperties,
|
||||
GeneratedClassDataForMethod classDataForMethod) {
|
||||
super(stubDefinition, configProperties, classDataForMethod)
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void given(BlockBuilder bb) {}
|
||||
|
||||
@Override
|
||||
protected void givenBlock(BlockBuilder bb) {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void when(BlockBuilder bb) {
|
||||
bb.addLine("def response = webTarget")
|
||||
bb.indent()
|
||||
|
||||
appendUrlPathAndQueryParameters(bb)
|
||||
appendRequestWithRequiredResponseContentType(bb)
|
||||
appendHeaders(bb)
|
||||
appendCookies(bb)
|
||||
appendMethodAndBody(bb)
|
||||
|
||||
bb.unindent()
|
||||
|
||||
bb.addEmptyLine()
|
||||
if (expectsResponseBody()) {
|
||||
bb.addLine("String responseAsString = response.readEntity(String)")
|
||||
}
|
||||
}
|
||||
|
||||
protected void appendRequestWithRequiredResponseContentType(BlockBuilder bb) {
|
||||
String acceptHeader = getHeader("Accept")
|
||||
if (acceptHeader) {
|
||||
bb.addLine(".request('$acceptHeader')")
|
||||
}
|
||||
else {
|
||||
bb.addLine(".request()")
|
||||
}
|
||||
}
|
||||
|
||||
protected void appendUrlPathAndQueryParameters(BlockBuilder bb) {
|
||||
if (request.url) {
|
||||
bb.addLine(".path(${concreteUrl(request.url)})")
|
||||
appendQueryParams(request.url.queryParameters, bb)
|
||||
}
|
||||
else if (request.urlPath) {
|
||||
bb.addLine(".path(${concreteUrl(request.urlPath)})")
|
||||
appendQueryParams(request.urlPath.queryParameters, bb)
|
||||
}
|
||||
}
|
||||
|
||||
protected String concreteUrl(DslProperty url) {
|
||||
Object testSideUrl = MapConverter.getTestSideValues(url)
|
||||
if (!(testSideUrl instanceof ExecutionProperty)) {
|
||||
return "'" + testSideUrl.toString() + "'"
|
||||
}
|
||||
return testSideUrl.toString()
|
||||
}
|
||||
|
||||
private void appendQueryParams(QueryParameters queryParameters, BlockBuilder bb) {
|
||||
if (!queryParameters?.parameters) {
|
||||
return
|
||||
}
|
||||
queryParameters.parameters.findAll(this.&allowedQueryParameter).
|
||||
each { QueryParameter param ->
|
||||
bb.addLine(".queryParam('$param.name', '${resolveParamValue(param).toString()}')")
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) {
|
||||
if (value.isByte()) {
|
||||
return "response.readEntity(byte[]) == " +
|
||||
readBytesFromFileString(value, CommunicationType.RESPONSE)
|
||||
}
|
||||
return getResponseBodyPropertyComparisonString(property, value.asString())
|
||||
}
|
||||
|
||||
protected void appendMethodAndBody(BlockBuilder bb) {
|
||||
String method = request.method.serverValue.toString().toLowerCase()
|
||||
if (request.body) {
|
||||
String contentType =
|
||||
getHeader('Content-Type') ?: getRequestContentType().mimeType
|
||||
Object body = request.body.serverValue
|
||||
String value
|
||||
if (body instanceof ExecutionProperty) {
|
||||
value = body.toString()
|
||||
}
|
||||
else if (body instanceof FromFileProperty) {
|
||||
FromFileProperty fileProperty = (FromFileProperty) body
|
||||
value = fileProperty.isByte() ?
|
||||
readBytesFromFileString(fileProperty, CommunicationType.REQUEST) :
|
||||
readStringFromFileString(fileProperty, CommunicationType.REQUEST)
|
||||
}
|
||||
else {
|
||||
value = "'${bodyAsString}'"
|
||||
}
|
||||
bb.addLine(".method('${method.toUpperCase()}', entity(${value}, '$contentType'))")
|
||||
}
|
||||
else {
|
||||
bb.addLine(".method('${method.toUpperCase()}')")
|
||||
}
|
||||
}
|
||||
|
||||
protected appendHeaders(BlockBuilder bb) {
|
||||
request.headers?.executeForEachHeader { Header header ->
|
||||
if (headerOfAbsentType(header)) {
|
||||
return
|
||||
}
|
||||
if (header.name == 'Content-Type' || header.name == 'Accept') {
|
||||
return
|
||||
} // Particular headers are set via 'request' / 'entity' methods
|
||||
bb.addLine(".header('${header.name}', '${header.serverValue}')")
|
||||
}
|
||||
}
|
||||
|
||||
protected appendCookies(BlockBuilder bb) {
|
||||
request.cookies?.executeForEachCookie { Cookie cookie ->
|
||||
if (cookieOfAbsentType(cookie)) {
|
||||
return
|
||||
}
|
||||
|
||||
bb.addLine(".cookie('${cookie.key}', '${cookie.serverValue}')")
|
||||
}
|
||||
}
|
||||
|
||||
protected String getHeader(String name) {
|
||||
return request.headers?.entries?.find { it.name == name }?.serverValue
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseCodeBlock(BlockBuilder bb) {
|
||||
bb.addLine("response.status == $response.status.serverValue")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseHeadersBlock(BlockBuilder bb) {
|
||||
response.headers?.executeForEachHeader { Header header ->
|
||||
processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ?
|
||||
header.serverValue :
|
||||
MapConverter.getTestSideValues(header.serverValue))
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void validateResponseCookiesBlock(BlockBuilder bb) {
|
||||
response.cookies?.executeForEachCookie { Cookie cookie ->
|
||||
processCookieElement(bb, cookie.key, cookie.serverValue instanceof NotToEscapePattern ?
|
||||
cookie.serverValue :
|
||||
MapConverter.getTestSideValues(cookie.serverValue))
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getResponseAsString() {
|
||||
return 'responseAsString'
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) {
|
||||
if (value instanceof NotToEscapePattern) {
|
||||
blockBuilder.
|
||||
addLine("response.getHeaderString('$property') ${convertHeaderComparison(((NotToEscapePattern) value).serverValue)}")
|
||||
}
|
||||
else {
|
||||
// fallback
|
||||
processHeaderElement(blockBuilder, property, value.toString())
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) {
|
||||
blockBuilder.
|
||||
addLine("${exec.insertValue("response.getHeaderString(\'$property\')")}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) {
|
||||
blockBuilder.
|
||||
addLine("response.getHeaderString('$property') ${convertHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) {
|
||||
blockBuilder.addLine("response.getHeaderString('$property') == ${value}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern value) {
|
||||
blockBuilder.
|
||||
addLine("response.getHeaderString('$property') ${convertHeaderComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) {
|
||||
blockBuilder.addLine("response.getCookies().get('$key') != null")
|
||||
blockBuilder.
|
||||
addLine("response.getCookies().get('$key').getValue() ${convertCookieComparison(pattern)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) {
|
||||
blockBuilder.addLine("response.getCookies().get('$key') != null")
|
||||
blockBuilder.
|
||||
addLine("response.getCookies().get('$key').getValue() ${convertCookieComparison(value)}")
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String postProcessJsonPathCall(String jsonPath) {
|
||||
if (templateProcessor.containsTemplateEntry(jsonPath)) {
|
||||
return jsonPath
|
||||
}
|
||||
return jsonPath.replace('$', '\\$')
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* 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.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JaxRsGiven implements Given, JaxRsAcceptor {
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
JaxRsGiven(GeneratedClassMetaData metaData) {
|
||||
this.generatedClassMetaData = metaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<Given> apply(SingleContractMetadata metadata) {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return acceptType(this.generatedClassMetaData, metadata);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* 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 java.util.Arrays;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.config.TestMode;
|
||||
|
||||
class JaxRsImports implements Imports {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private static final String[] IMPORTS = { "javax.ws.rs.client.Entity",
|
||||
"javax.ws.rs.core.Response" };
|
||||
|
||||
JaxRsImports(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Imports call() {
|
||||
Arrays.stream(IMPORTS)
|
||||
.forEach(s -> this.blockBuilder.addLineWithEnding("import " + s));
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept() {
|
||||
return this.generatedClassMetaData.configProperties
|
||||
.getTestMode() == TestMode.JAXRSCLIENT;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* 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 java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.Cookie;
|
||||
import org.springframework.cloud.contract.spec.internal.MatchingStrategy;
|
||||
import org.springframework.cloud.contract.spec.internal.Request;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JaxRsRequestCookiesWhen implements When {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final BodyParser bodyParser;
|
||||
|
||||
JaxRsRequestCookiesWhen(BlockBuilder blockBuilder, BodyParser bodyParser) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.bodyParser = bodyParser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<When> apply(SingleContractMetadata metadata) {
|
||||
appendCookies(metadata.getContract().getRequest());
|
||||
return this;
|
||||
}
|
||||
|
||||
private void appendCookies(Request request) {
|
||||
Iterator<Cookie> iterator = request.getCookies().getEntries().stream()
|
||||
.filter(cookie -> !cookieOfAbsentType(cookie)).iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Cookie cookie = iterator.next();
|
||||
String value = ".cookie(" + this.bodyParser.quotedShortText(cookie.getKey())
|
||||
+ ", " + this.bodyParser.quotedShortText(cookie.getServerValue())
|
||||
+ ")";
|
||||
if (iterator.hasNext()) {
|
||||
this.blockBuilder.addLine(value);
|
||||
}
|
||||
else {
|
||||
this.blockBuilder.addIndented(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean cookieOfAbsentType(Cookie cookie) {
|
||||
return cookie.getServerValue() instanceof MatchingStrategy
|
||||
&& ((MatchingStrategy) cookie.getServerValue())
|
||||
.getType() == MatchingStrategy.Type.ABSENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return metadata.getContract().getRequest().getCookies() != null && !metadata
|
||||
.getContract().getRequest().getCookies().getEntries().isEmpty()
|
||||
&& !hasOnlyAbsentCookies(metadata);
|
||||
}
|
||||
|
||||
private boolean hasOnlyAbsentCookies(SingleContractMetadata metadata) {
|
||||
Set<Cookie> entries = metadata.getContract().getRequest().getCookies()
|
||||
.getEntries();
|
||||
long filteredOut = entries.stream().filter(this::cookieOfAbsentType).count();
|
||||
return filteredOut == entries.size();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* 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 java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.Header;
|
||||
import org.springframework.cloud.contract.spec.internal.MatchingStrategy;
|
||||
import org.springframework.cloud.contract.spec.internal.Request;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JaxRsRequestHeadersWhen implements When {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final BodyParser bodyParser;
|
||||
|
||||
JaxRsRequestHeadersWhen(BlockBuilder blockBuilder, BodyParser bodyParser) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.bodyParser = bodyParser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<When> apply(SingleContractMetadata metadata) {
|
||||
appendHeaders(metadata.getContract().getRequest());
|
||||
return this;
|
||||
}
|
||||
|
||||
private void appendHeaders(Request request) {
|
||||
Iterator<Header> iterator = request.getHeaders().getEntries().stream()
|
||||
.filter(header -> !headerToIgnore(header)).iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Header header = iterator.next();
|
||||
String text = ".header(\"" + header.getName() + "\", "
|
||||
+ this.bodyParser.quotedLongText(header.getServerValue()) + ")";
|
||||
if (iterator.hasNext()) {
|
||||
this.blockBuilder.addLine(text);
|
||||
}
|
||||
else {
|
||||
this.blockBuilder.addIndented(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean headerToIgnore(Header header) {
|
||||
return contentTypeOrAccept(header) || headerOfAbsentType(header);
|
||||
}
|
||||
|
||||
private boolean contentTypeOrAccept(Header header) {
|
||||
return "Content-Type".equalsIgnoreCase(header.getName())
|
||||
|| "Accept".equalsIgnoreCase(header.getName());
|
||||
}
|
||||
|
||||
private boolean headerOfAbsentType(Header header) {
|
||||
return header.getServerValue() instanceof MatchingStrategy
|
||||
&& ((MatchingStrategy) header.getServerValue())
|
||||
.getType() == MatchingStrategy.Type.ABSENT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return metadata.getContract().getRequest().getHeaders() != null && !metadata
|
||||
.getContract().getRequest().getHeaders().getEntries().isEmpty()
|
||||
&& !hasHeaderOnlyContentTypeOrAccept(metadata);
|
||||
}
|
||||
|
||||
private boolean hasHeaderOnlyContentTypeOrAccept(SingleContractMetadata metadata) {
|
||||
Set<Header> entries = metadata.getContract().getRequest().getHeaders()
|
||||
.getEntries();
|
||||
long filteredOut = entries.stream().filter(this::headerToIgnore).count();
|
||||
return filteredOut == entries.size();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* 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.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JaxRsRequestInvokerWhen implements When, JaxRsBodyParser {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
JaxRsRequestInvokerWhen(BlockBuilder blockBuilder) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<When> apply(SingleContractMetadata metadata) {
|
||||
this.blockBuilder.addIndented(".invoke()").addEndingIfNotPresent();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* 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.ExecutionProperty;
|
||||
import org.springframework.cloud.contract.spec.internal.FromFileProperty;
|
||||
import org.springframework.cloud.contract.spec.internal.Header;
|
||||
import org.springframework.cloud.contract.spec.internal.Request;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
import org.springframework.cloud.contract.verifier.util.ContentType;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
class JaxRsRequestMethodWhen implements When, JaxRsBodyParser {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final BodyReader bodyReader;
|
||||
|
||||
JaxRsRequestMethodWhen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.bodyReader = new BodyReader(metaData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<When> apply(SingleContractMetadata metadata) {
|
||||
appendMethodAndBody(metadata);
|
||||
return this;
|
||||
}
|
||||
|
||||
void appendMethodAndBody(SingleContractMetadata metadata) {
|
||||
Request request = metadata.getContract().getRequest();
|
||||
ContentType type = metadata.getInputTestContentType();
|
||||
String method = request.getMethod().getServerValue().toString().toLowerCase();
|
||||
if (request.getBody() != null) {
|
||||
String contentType = type.getMimeType();
|
||||
contentType = StringUtils.hasText(contentType) ? contentType
|
||||
: getContentType(request);
|
||||
Object body = request.getBody().getServerValue();
|
||||
String value;
|
||||
if (body instanceof ExecutionProperty) {
|
||||
value = body.toString();
|
||||
}
|
||||
else if (body instanceof FromFileProperty) {
|
||||
FromFileProperty fileProperty = (FromFileProperty) body;
|
||||
value = fileProperty.isByte()
|
||||
? this.bodyReader.readBytesFromFileString(metadata, fileProperty,
|
||||
CommunicationType.REQUEST)
|
||||
: this.bodyReader.readStringFromFileString(metadata, fileProperty,
|
||||
CommunicationType.REQUEST);
|
||||
}
|
||||
else {
|
||||
value = "\"" + requestBodyAsString(metadata) + "\"";
|
||||
}
|
||||
this.blockBuilder.addIndented(".build(\"" + method.toUpperCase()
|
||||
+ "\", entity(" + value + ", \"" + contentType + "\"))");
|
||||
}
|
||||
else {
|
||||
this.blockBuilder.addIndented(".build(\"" + method.toUpperCase() + "\")");
|
||||
}
|
||||
}
|
||||
|
||||
private String getContentType(Request request) {
|
||||
Header contentType = request.getHeaders().getEntries().stream()
|
||||
.filter(header -> "Content-Type".equalsIgnoreCase(header.getName()))
|
||||
.findFirst().orElse(null);
|
||||
return contentType != null ? contentType.getServerValue().toString() : "";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* 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.Header;
|
||||
import org.springframework.cloud.contract.spec.internal.Request;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
class JaxRsRequestWhen implements When, JaxRsAcceptor, QueryParamsResolver {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
JaxRsRequestWhen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = metaData;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<When> apply(SingleContractMetadata metadata) {
|
||||
appendRequestWithRequiredResponseContentType(metadata.getContract().getRequest());
|
||||
return this;
|
||||
}
|
||||
|
||||
void appendRequestWithRequiredResponseContentType(Request request) {
|
||||
String acceptHeader = getHeader(request, "Accept");
|
||||
if (StringUtils.hasText(acceptHeader)) {
|
||||
this.blockBuilder.addIndented(".request(\"" + acceptHeader + "\")");
|
||||
}
|
||||
else {
|
||||
this.blockBuilder.addIndented(".request()");
|
||||
}
|
||||
}
|
||||
|
||||
private String getHeader(Request request, String name) {
|
||||
if (request.getHeaders() == null || request.getHeaders().getEntries() == null) {
|
||||
return "";
|
||||
}
|
||||
Header foundHeader = request.getHeaders().getEntries().stream()
|
||||
.filter(header -> name.equals(header.getName())).findFirst().orElse(null);
|
||||
if (foundHeader == null) {
|
||||
return "";
|
||||
}
|
||||
return foundHeader.getServerValue().toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return acceptType(this.generatedClassMetaData, metadata);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.Response;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
class JaxRsResponseCookiesThen implements Then, MockMvcAcceptor, CookieElementProcessor {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private final ComparisonBuilder comparisonBuilder;
|
||||
|
||||
private final BodyParser bodyParser;
|
||||
|
||||
JaxRsResponseCookiesThen(BlockBuilder blockBuilder,
|
||||
GeneratedClassMetaData generatedClassMetaData,
|
||||
ComparisonBuilder comparisonBuilder) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = generatedClassMetaData;
|
||||
this.comparisonBuilder = comparisonBuilder;
|
||||
this.bodyParser = comparisonBuilder.bodyParser();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<Then> apply(SingleContractMetadata metadata) {
|
||||
processCookies(metadata);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ComparisonBuilder comparisonBuilder() {
|
||||
return this.comparisonBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockBuilder blockBuilder() {
|
||||
return this.blockBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String cookieKey(String key) {
|
||||
return "response.getCookies().get(" + this.bodyParser.quotedShortText(key) + ")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String cookieValue(String key) {
|
||||
return cookieKey(key) + ".getValue()";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
Response response = metadata.getContract().getResponse();
|
||||
return response.getCookies() != null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* 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 java.util.Iterator;
|
||||
|
||||
import org.springframework.cloud.contract.spec.internal.ExecutionProperty;
|
||||
import org.springframework.cloud.contract.spec.internal.Header;
|
||||
import org.springframework.cloud.contract.spec.internal.Headers;
|
||||
import org.springframework.cloud.contract.spec.internal.NotToEscapePattern;
|
||||
import org.springframework.cloud.contract.spec.internal.Response;
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
import org.springframework.cloud.contract.verifier.util.MapConverter;
|
||||
|
||||
class JaxRsResponseHeadersThen implements Then {
|
||||
|
||||
private final BlockBuilder blockBuilder;
|
||||
|
||||
private final GeneratedClassMetaData generatedClassMetaData;
|
||||
|
||||
private final ComparisonBuilder comparisonBuilder;
|
||||
|
||||
JaxRsResponseHeadersThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData,
|
||||
ComparisonBuilder comparisonBuilder) {
|
||||
this.blockBuilder = blockBuilder;
|
||||
this.generatedClassMetaData = metaData;
|
||||
this.comparisonBuilder = comparisonBuilder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodVisitor<Then> apply(SingleContractMetadata metadata) {
|
||||
validateResponseHeadersBlock(metadata);
|
||||
return this;
|
||||
}
|
||||
|
||||
private void validateResponseHeadersBlock(SingleContractMetadata metadata) {
|
||||
Response response = metadata.getContract().getResponse();
|
||||
Headers headers = response.getHeaders();
|
||||
Iterator<Header> iterator = headers.getEntries().iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Header header = iterator.next();
|
||||
String text = processHeaderElement(header.getName(),
|
||||
header.getServerValue() instanceof NotToEscapePattern
|
||||
? header.getServerValue()
|
||||
: MapConverter.getTestSideValues(header.getServerValue()));
|
||||
if (iterator.hasNext()) {
|
||||
this.blockBuilder.addLineWithEnding(text);
|
||||
}
|
||||
else {
|
||||
this.blockBuilder.addIndented(text);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private String processHeaderElement(String property, Object value) {
|
||||
if (value instanceof NotToEscapePattern) {
|
||||
return this.comparisonBuilder
|
||||
.assertThat("response.getHeaderString(\"" + property + "\")")
|
||||
+ this.comparisonBuilder.createComparison(
|
||||
((NotToEscapePattern) value).getServerValue());
|
||||
}
|
||||
else if (value instanceof Number) {
|
||||
return this.comparisonBuilder
|
||||
.assertThat("response.getHeaderString(\"" + property + "\")", value);
|
||||
}
|
||||
else if (value instanceof ExecutionProperty) {
|
||||
return ((ExecutionProperty) value)
|
||||
.insertValue("response.getHeaderString(\"" + property + "\")");
|
||||
}
|
||||
else {
|
||||
return this.comparisonBuilder
|
||||
.assertThat("response.getHeaderString(\"" + property + "\")")
|
||||
+ this.comparisonBuilder.createComparison(value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return metadata.getContract().getResponse().getHeaders() != null;
|
||||
}
|
||||
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user