diff --git a/docs/src/main/asciidoc/verifier/contract.adoc b/docs/src/main/asciidoc/verifier/contract.adoc index f532f683b4..88128fd1e2 100644 --- a/docs/src/main/asciidoc/verifier/contract.adoc +++ b/docs/src/main/asciidoc/verifier/contract.adoc @@ -427,7 +427,7 @@ Thanks to the interface [source,groovy] ---- -include::{contract_spec_path}/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.groovy[indent=0] +include::{contract_spec_path}/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.groovy[indent=0,lines=17..-1] ---- you can register your own implementation of a contract structure converter. @@ -441,14 +441,14 @@ Example of a `spring.factories` file [source] ---- -include::{verifier_core_path}/src/main/resources/META-INF/spring.factories[indent=0] +include::{verifier_core_path}/src/test/resources/META-INF/spring.factories[indent=0] ---- and the YAML implementation [source,groovy] ---- -include::{verifier_core_path}/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy[indent=0] +include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy[indent=0,lines=16..-1] ---- ==== Custom test generator @@ -461,7 +461,7 @@ Thanks to the interface [source,groovy] ---- -include::{verifier_core_path}/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy[indent=0] +include::{verifier_core_path}/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy[indent=0,lines=17..-1] ---- you can register your own implementation that generates a test. Again, it's enough to provide @@ -480,7 +480,7 @@ If you want to generate stubs for other stub server than WireMock it's enough to [source,groovy] ---- -include::{converters_path}/src/main/groovy/org/springframework/cloud/contract/verifier/converter/SingleFileConverter.groovy[indent=0] +include::{converters_path}/src/main/groovy/org/springframework/cloud/contract/verifier/converter/SingleFileConverter.groovy[indent=0,lines=16..-1] ---- you can register your own implementation that generate Stubs. Again, it's enough to provide diff --git a/docs/src/main/asciidoc/verifier/stubrunner_msg.adoc b/docs/src/main/asciidoc/verifier/stubrunner_msg.adoc index 776bdff84c..09d6cc6ed5 100644 --- a/docs/src/main/asciidoc/verifier/stubrunner_msg.adoc +++ b/docs/src/main/asciidoc/verifier/stubrunner_msg.adoc @@ -15,7 +15,7 @@ To trigger a message it's enough to use the `StubTrigger` interface: [source,groovy] ---- -include::{stubrunner_core_path}/src/main/java/org/springframework/cloud/contract/stubrunner/StubTrigger.java[] +include::{stubrunner_core_path}/src/main/java/org/springframework/cloud/contract/stubrunner/StubTrigger.java[lines=16..-1] ---- For convenience the `StubFinder` interface extends `StubTrigger` so it's enough to use only one in your tests. diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.groovy index 68c0d8fe45..6ffcc0d568 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/ContractConverter.groovy @@ -1,3 +1,19 @@ +/* + * Copyright 2013-2016 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 + * + * http://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.spec /** @@ -26,7 +42,7 @@ public interface ContractConverter { * @param file - file to convert * @return - {@link Contract} representation of the file */ - Contract convertFrom(File file) + Collection convertFrom(File file) /** * Converts the given {@link Contract} to a {@link T} representation @@ -34,5 +50,5 @@ public interface ContractConverter { * @param contract - the parsed contract * @return - {@link T} the type to which we do the conversion */ - T convertTo(Contract contract) + T convertTo(Collection contract) } diff --git a/spring-cloud-contract-stub-runner/README.adoc b/spring-cloud-contract-stub-runner/README.adoc index 611a3c2290..50b3f3d51b 100644 --- a/spring-cloud-contract-stub-runner/README.adoc +++ b/spring-cloud-contract-stub-runner/README.adoc @@ -100,7 +100,7 @@ Since the `StubRunnerRule` implements the `StubFinder` it allows you to find the [source,groovy,indent=0] ---- -include::src/main/java/org/springframework/cloud/contract/stubrunner/StubFinder.java[] +include::src/main/java/org/springframework/cloud/contract/stubrunner/StubFinder.java[lines=16..-1] ---- Example of usage in Spock tests: diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/SingleFileConverter.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/SingleFileConverter.groovy index 9fd8269d07..348408bd48 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/SingleFileConverter.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/converter/SingleFileConverter.groovy @@ -33,12 +33,24 @@ interface SingleFileConverter { boolean canHandleFileName(String fileName) /** - * Returns the content of the converted file. The content will be the stub. + * Returns the content of the converted file. The content will be a single stub. */ + @Deprecated String convertContent(String rootName, ContractMetadata content) /** - * Returns the name of the converted stub file. + * Returns the collection of converted contracts into stubs. One contract can + * result in multiple stubs. + */ + Collection convertContents(String rootName, ContractMetadata content) + + /** + * Returns the name of the converted stub file. If you have multiple contracts + * in a single file then a prefix will be added to the generated file. + * + * Example: name of file with 2 contracts is {@code foo.groovy}, it will be + * converted by the implementation to {@code foo.json}. The recursive file + * converter will create two files {@code 0_foo.json} and {@code 1_foo.json} */ String generateOutputFileNameForInput(String inputFileName) } \ No newline at end of file diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverter.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverter.groovy index 50bc8b752a..62f8df0137 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverter.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverter.groovy @@ -17,6 +17,7 @@ package org.springframework.cloud.contract.verifier.wiremock import groovy.transform.CompileStatic +import org.springframework.cloud.contract.spec.Contract import org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockStubStrategy import org.springframework.cloud.contract.verifier.file.ContractMetadata @@ -31,10 +32,26 @@ import java.nio.charset.StandardCharsets class DslToWireMockClientConverter extends DslToWireMockConverter { @Override + @Deprecated String convertContent(String rootName, ContractMetadata contract) { - return new WireMockStubStrategy(rootName, contract, - contract.convertedContract ?: createGroovyDSLFromStringContent( - contract.path.getText(StandardCharsets.UTF_8.toString())) - ).toWireMockClientStub() + return convertASingleContract(rootName, contract, contract.convertedContract.first() ?: createGroovyDSLFromStringContent( + contract.path.getText(StandardCharsets.UTF_8.toString())).first()) + } + + private String convertASingleContract(String rootName, ContractMetadata contract, Contract dsl) { + return new WireMockStubStrategy(rootName, contract, dsl).toWireMockClientStub() + } + + @Override + Collection convertContents(String rootName, ContractMetadata contract) { + if (contract.convertedContract.size() == 1) { + return [convertASingleContract(rootName, contract, contract.convertedContract.first())] + } + List convertedContracts = [] + contract.convertedContract.eachWithIndex { Contract dsl, int index -> + String name = "${rootName}_${index}" + convertedContracts << convertASingleContract(name, contract, dsl) + } + return convertedContracts } } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockConverter.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockConverter.groovy index 2d16614559..bdecb3c386 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockConverter.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockConverter.groovy @@ -47,7 +47,7 @@ abstract class DslToWireMockConverter implements SingleFileConverter { return "" } - protected Contract createGroovyDSLFromStringContent(String groovyDslAsString) { - return ContractVerifierDslConverter.convert(groovyDslAsString) + protected List createGroovyDSLFromStringContent(String groovyDslAsString) { + return ContractVerifierDslConverter.convertAsCollection(groovyDslAsString) } } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy index 1a5f55fb0e..4a7373bb78 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/main/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverter.groovy @@ -19,6 +19,7 @@ package org.springframework.cloud.contract.verifier.wiremock import com.google.common.collect.ListMultimap import groovy.transform.CompileStatic import groovy.util.logging.Slf4j +import org.springframework.cloud.contract.spec.Contract import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties import org.springframework.cloud.contract.verifier.converter.SingleFileConverter import org.springframework.cloud.contract.verifier.converter.SingleFileConvertersHolder @@ -85,13 +86,17 @@ class RecursiveFilesConverter { if (!contract.convertedContract && !singleFileConverter) { return } - String convertedContent = singleFileConverter.convertContent(entry.key.last().toString(), contract) - if (!convertedContent) { - return + int contractsSize = contract.convertedContract.size() + contract.convertedContract.eachWithIndex { Contract dsl, int index -> + String convertedContent = singleFileConverter.convertContent(entry.key.last().toString(), contract) + if (!convertedContent) { + return + } + Path absoluteTargetPath = createAndReturnTargetDirectory(sourceFile) + File newJsonFile = createTargetFileWithProperName(singleFileConverter, absoluteTargetPath, + sourceFile, contractsSize, index) + newJsonFile.setText(convertedContent, StandardCharsets.UTF_8.toString()) } - Path absoluteTargetPath = createAndReturnTargetDirectory(sourceFile) - File newJsonFile = createTargetFileWithProperName(singleFileConverter, absoluteTargetPath, sourceFile) - newJsonFile.setText(convertedContent, StandardCharsets.UTF_8.toString()) } catch (Exception e) { throw new ConversionContractVerifierException("Unable to make conversion of ${sourceFile.name}", e) } @@ -106,8 +111,11 @@ class RecursiveFilesConverter { return absoluteTargetPath } - private File createTargetFileWithProperName(SingleFileConverter singleFileConverter, Path absoluteTargetPath, File sourceFile) { - File newJsonFile = new File(absoluteTargetPath.toFile(), singleFileConverter.generateOutputFileNameForInput(sourceFile.name)) + private File createTargetFileWithProperName(SingleFileConverter singleFileConverter, Path absoluteTargetPath, + File sourceFile, int contractsSize, int index) { + String generatedName = singleFileConverter.generateOutputFileNameForInput(sourceFile.name) + String name = contractsSize == 1 ? generatedName : "${index}_${generatedName}" + File newJsonFile = new File(absoluteTargetPath.toFile(), name) log.info("Creating new json [$newJsonFile.path]") return newJsonFile } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy index 38ca8f3d2c..debe34c0bb 100755 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy @@ -27,7 +27,7 @@ import spock.lang.Specification class DslToWireMockClientConverterSpec extends Specification { @Rule - public TemporaryFolder tmpFolder = new TemporaryFolder(); + public TemporaryFolder tmpFolder = new TemporaryFolder() def "should convert DSL file to WireMock JSON"() { given: @@ -53,6 +53,39 @@ class DslToWireMockClientConverterSpec extends Specification { ''', json, false) } + def "should convert DSL file with list of contracts to WireMock JSONs"() { + given: + def converter = new DslToWireMockClientConverter() + and: + File file = tmpFolder.newFile("dsl1_list.groovy") + file.write(''' +(1..2).collect { int index -> + org.springframework.cloud.contract.spec.Contract.make { + request { + method(PUT()) + headers { + contentType(applicationJson()) + } + url "/${index}" + } + response { + status 200 + } + } +} +''') + when: + List json = converter.convertContents("Test", new ContractMetadata(file.toPath(), false, 0, null)) + then: + json.size() == 2 + JSONAssert.assertEquals(jsonResponse(1), json.first(), false) + JSONAssert.assertEquals(jsonResponse(2), json.last(), false) + } + + private String jsonResponse(int index) { + return """{"request":{"method":"PUT","url":"/${index}"},"response":{"status":200}}""" + } + @Issue("196") def "should creation of delayed stub responses be possible"() { given: diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverterSpec.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverterSpec.groovy index 221bcba091..a5137f21b6 100755 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverterSpec.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/RecursiveFilesConverterSpec.groovy @@ -33,7 +33,9 @@ import spock.lang.Specification class RecursiveFilesConverterSpec extends Specification { private static - final Set EXPECTED_TARGET_FILES = [Paths.get("dslRoot.json"), Paths.get("dir1/dsl1.json"), Paths.get("dir1/dsl1b.json"), Paths.get("dir2/dsl2.json")] + final Set EXPECTED_TARGET_FILES = [Paths.get("dslRoot.json"), Paths.get("dir1/dsl1.json"), + Paths.get("dir1/dsl1b.json"), Paths.get("dir2/dsl2.json"), + Paths.get("dir1/0_dsl1_list.json"), Paths.get("dir1/1_dsl1_list.json")] @Rule public TemporaryFolder tmpFolder = new TemporaryFolder(); diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/resources/converter/source/dir1/dsl1_list.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/resources/converter/source/dir1/dsl1_list.groovy new file mode 100644 index 0000000000..292c101620 --- /dev/null +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/resources/converter/source/dir1/dsl1_list.groovy @@ -0,0 +1,32 @@ +import org.springframework.cloud.contract.spec.Contract + +/* + * Copyright 2013-2016 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 + * + * http://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. + */ + +(1..2).collect { int index -> + Contract.make { + request { + method(PUT()) + headers { + contentType(applicationJson()) + } + url "/${index}" + } + response { + status 200 + } + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/pom.xml b/spring-cloud-contract-verifier/pom.xml index eee88d8ca6..84141851f1 100644 --- a/spring-cloud-contract-verifier/pom.xml +++ b/spring-cloud-contract-verifier/pom.xml @@ -45,12 +45,6 @@ spring-rabbit true - - org.yaml - snakeyaml - - - javax.inject javax.inject @@ -111,6 +105,11 @@ slf4j-simple test + + org.yaml + snakeyaml + test + diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaTestGenerator.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaTestGenerator.groovy index b1accfa9c2..b8c8bfe1ee 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaTestGenerator.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaTestGenerator.groovy @@ -106,15 +106,19 @@ class JavaTestGenerator implements SingleTestGenerator { } private Map mapContractsToTheirTestTypes(Collection listOfFiles) { - return listOfFiles.collectEntries { - File stubsFile = it.path.toFile() + Map dsls = [:] + listOfFiles.each { ContractMetadata metadata -> + File stubsFile = metadata.path.toFile() if (log.isDebugEnabled()) { log.debug("Stub content from file [${stubsFile.text}]") } - Contract stubContent = it.convertedContract - TestType testType = (stubContent.input || stubContent.outputMessage) ? TestType.MESSAGING : TestType.HTTP - return [(new ParsedDsl(it, stubContent, stubsFile)): testType] + List stubContents = metadata.convertedContract + dsls << stubContents.collectEntries { Contract stubContent -> + TestType testType = (stubContent.input || stubContent.outputMessage) ? TestType.MESSAGING : TestType.HTTP + return [(new ParsedDsl(metadata, stubContent, stubsFile)): testType] + } } + return dsls } @Canonical diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.groovy deleted file mode 100644 index dec6552123..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.groovy +++ /dev/null @@ -1,26 +0,0 @@ -package org.springframework.cloud.contract.verifier.converter - -/** - * Yaml representation of a {@link org.springframework.cloud.contract.spec.Contract} - * - * @author Marcin Grzejszczak - * @since 1.0.3 - */ -//TODO: Perform full conversion -class YamlContract { - public Request request = new Request() - public Response response = new Response() - - static class Request { - public String method - public String url - public Map headers = [:] - public Map body = [:] - } - - static class Response { - public int status - public Map headers = [:] - public Map body = [:] - } -} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy deleted file mode 100644 index b477e099c9..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy +++ /dev/null @@ -1,73 +0,0 @@ -package org.springframework.cloud.contract.verifier.converter - -import groovy.transform.CompileStatic -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.ContractConverter -import org.springframework.cloud.contract.spec.internal.Headers -import org.yaml.snakeyaml.Yaml - -/** - * Converter from and to a {@link YamlContract} to a {@link Contract} - * - * @author Marcin Grzejszczak - * @since 1.0.3 - */ -//TODO: Perform full conversion -@CompileStatic -class YamlContractConverter implements ContractConverter { - - @Override - public boolean isAccepted(File file) { - String name = file.getName() - return name.endsWith(".yml") || name.endsWith(".yaml") - } - - @Override - public Contract convertFrom(File file) { - try { - YamlContract yamlContract = new Yaml().loadAs(new FileInputStream(file), YamlContract.class) - return Contract.make { - request { - method(yamlContract?.request?.method) - url(yamlContract?.request?.url) - headers { - yamlContract?.request?.headers?.each { String key, Object value -> - header(key, value) - } - } - body(yamlContract?.request?.body) - } - response { - status(yamlContract?.response?.status) - headers { - yamlContract?.response?.headers?.each { String key, Object value -> - header(key, value) - } - } - body(yamlContract?.response?.body) - } - } - } - catch (FileNotFoundException e) { - throw new IllegalStateException(e) - } - } - - @Override - public YamlContract convertTo(Contract contract) { - // TODO: Pick one of the sides - consumer / producer - YamlContract yamlContract = new YamlContract() - yamlContract.request.with { - method = contract?.request?.method?.clientValue - url = contract?.request?.url?.clientValue - headers = (contract?.request?.headers as Headers)?.asStubSideMap() - body = contract?.request?.body?.clientValue as Map - } - yamlContract.response.with { - status = contract?.response?.status?.clientValue as Integer - headers = (contract?.response?.headers as Headers)?.asStubSideMap() - body = contract?.response?.body?.clientValue as Map - } - return yamlContract - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy index 7a9f303b51..a9204a0c8e 100755 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScanner.groovy @@ -94,7 +94,7 @@ class ContractFileScanner { boolean contractFile = isContractFile(file) boolean included = includeMatcher ? file.absolutePath.matches(includeMatcher) : true if (contractFile && included) { - addContractToTestGeneration(result, files, file, index, ContractVerifierDslConverter.convert(file)) + addContractToTestGeneration(result, files, file, index, ContractVerifierDslConverter.convertAsCollection(file)) } else if (!contractFile && included) { addContractToTestGeneration(converters, result, files, file, index) } else { @@ -130,7 +130,7 @@ class ContractFileScanner { } private void addContractToTestGeneration(ListMultimap result, File[] files, File file, - int index, Contract convertedContract) { + int index, Collection convertedContract) { Path path = file.toPath() Integer order = null if (hasScenarioFilenamePattern(path)) { diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy index 81cf3a1eac..1246cb282c 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/file/ContractMetadata.groovy @@ -19,6 +19,7 @@ package org.springframework.cloud.contract.verifier.file import groovy.transform.CompileStatic import groovy.transform.ToString import org.springframework.cloud.contract.spec.Contract +import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter import java.nio.file.Path /** @@ -44,20 +45,28 @@ class ContractMetadata { */ final int groupSize /** - * If scenario related will + * If scenario related will contain an order of execution */ final Integer order /** - * When we have already converted a contract via a converter this - * field will be set + * The list of contracts for the given file */ - final Contract convertedContract + final Collection convertedContract = [] - ContractMetadata(Path path, boolean ignored, int groupSize, Integer order, Contract convertedContract = null) { + @Deprecated + ContractMetadata(Path path, boolean ignored, int groupSize, Integer order) { + this(path, ignored, groupSize, order, ContractVerifierDslConverter.convertAsCollection(path.toFile())) + } + + ContractMetadata(Path path, boolean ignored, int groupSize, Integer order, Contract convertedContract) { + this(path, ignored, groupSize, order, [convertedContract]) + } + + ContractMetadata(Path path, boolean ignored, int groupSize, Integer order, Collection convertedContract) { this.groupSize = groupSize this.path = path this.ignored = ignored this.order = order - this.convertedContract = convertedContract + this.convertedContract.addAll(convertedContract) } } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContractVerifierDslConverter.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContractVerifierDslConverter.groovy index 9cd8eb5956..b2031b659e 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContractVerifierDslConverter.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContractVerifierDslConverter.groovy @@ -17,6 +17,7 @@ package org.springframework.cloud.contract.verifier.util import groovy.transform.CompileStatic +import groovy.util.logging.Slf4j import org.codehaus.groovy.control.CompilerConfiguration import org.springframework.cloud.contract.spec.Contract @@ -28,17 +29,63 @@ import org.springframework.cloud.contract.spec.Contract * @since 1.0.0 */ @CompileStatic +@Slf4j class ContractVerifierDslConverter { + @Deprecated static Contract convert(String dsl) { - return groovyShell().evaluate(dsl) as Contract + try { + return groovyShell().evaluate(dsl) as Contract + } catch (Exception e) { + log.error("Exception occurred while trying to evaluate the contract", e) + throw new DslParseException(e) + } } + @Deprecated static Contract convert(File dsl) { - return groovyShell().evaluate(dsl) as Contract + try { + return groovyShell().evaluate(dsl) as Contract + } catch (Exception e) { + log.error("Exception occurred while trying to evaluate the contract", e) + throw new DslParseException(e) + } + } + + static Collection convertAsCollection(String dsl) { + try { + Object object = groovyShell().evaluate(dsl) + return listOfContracts(object) + } catch (DslParseException e) { + throw e + } catch (Exception e) { + log.error("Exception occurred while trying to evaluate the contract", e) + throw new DslParseException(e) + } + } + + static Collection convertAsCollection(File dsl) { + try { + Object object = groovyShell().evaluate(dsl) + return listOfContracts(object) + } catch (DslParseException e) { + throw e + } catch (Exception e) { + log.error("Exception occurred while trying to evaluate the contract at path [${dsl.path}]", e) + throw new DslParseException(e) + } } private static GroovyShell groovyShell() { return new GroovyShell(ContractVerifierDslConverter.classLoader, new Binding(), new CompilerConfiguration(sourceEncoding: 'UTF-8')) } + + private static List listOfContracts(object) { + if (object instanceof Collection) { + return object as Collection + } else if (!object instanceof Contract) { + throw new DslParseException("Contract is not returning a Contract or list of Contracts") + } + return [object] as Collection + } } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DslParseException.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DslParseException.groovy new file mode 100644 index 0000000000..307855eab3 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/DslParseException.groovy @@ -0,0 +1,29 @@ +/* + * Copyright 2013-2016 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 + * + * http://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.util + +import groovy.transform.InheritConstructors + +/** + * Exception occurring when we're trying to parse the DSL + * + * @author Marcin Grzejszczak + * @since 1.0.3 + */ +@InheritConstructors +class DslParseException extends RuntimeException { +} diff --git a/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories b/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories index 505fcced9c..0e6be1c75d 100644 --- a/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories +++ b/spring-cloud-contract-verifier/src/main/resources/META-INF/spring.factories @@ -5,8 +5,4 @@ org.springframework.cloud.contract.verifier.messaging.integration.ContractVerifi org.springframework.cloud.contract.verifier.messaging.amqp.ContractVerifierAmqpAutoConfiguration,\ org.springframework.cloud.contract.verifier.messaging.amqp.RabbitMockConnectionFactoryAutoConfiguration,\ org.springframework.cloud.contract.verifier.messaging.camel.ContractVerifierCamelConfiguration,\ -org.springframework.cloud.contract.verifier.messaging.noop.NoOpContractVerifierAutoConfiguration - -# Converters -org.springframework.cloud.contract.spec.ContractConverter=\ -org.springframework.cloud.contract.verifier.converter.YamlContractConverter \ No newline at end of file +org.springframework.cloud.contract.verifier.messaging.noop.NoOpContractVerifierAutoConfiguration \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy index ed65535af0..4750666bb9 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientMethodBuilderSpec.groovy @@ -86,7 +86,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").isNull()""") blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("true")""") and: - stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), contractDsl).toWireMockClientStub()) + stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, contractDsl), contractDsl).toWireMockClientStub()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -121,7 +121,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("a").isEqualTo("sth")""") blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("b").isEqualTo("sthElse")""") and: - stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), contractDsl).toWireMockClientStub()) + stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, contractDsl), contractDsl).toWireMockClientStub()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -159,7 +159,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").hasSize(2)""") blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("b").isEqualTo("sthElse")""") and: - stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), contractDsl).toWireMockClientStub()) + stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, contractDsl), contractDsl).toWireMockClientStub()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.groovy new file mode 100644 index 0000000000..92e729cf16 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContract.groovy @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2016 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 + * + * http://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.converter + +/** + * Yaml representation of a {@link org.springframework.cloud.contract.spec.Contract} + */ +class YamlContract { + public Request request = new Request() + public Response response = new Response() + + static class Request { + public String method + public String url + public Map headers = [:] + public Map body = [:] + } + + static class Response { + public int status + public Map headers = [:] + public Map body = [:] + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy new file mode 100644 index 0000000000..a7016d8fe6 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverter.groovy @@ -0,0 +1,86 @@ +/* + * Copyright 2013-2016 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 + * + * http://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.converter + +import groovy.transform.CompileStatic +import org.springframework.cloud.contract.spec.Contract +import org.springframework.cloud.contract.spec.ContractConverter +import org.springframework.cloud.contract.spec.internal.Headers +import org.yaml.snakeyaml.Yaml + +/** + * Simple converter from and to a {@link YamlContract} to a collection of {@link Contract} + */ +@CompileStatic +class YamlContractConverter implements ContractConverter> { + + @Override + public boolean isAccepted(File file) { + String name = file.getName() + return name.endsWith(".yml") || name.endsWith(".yaml") + } + + @Override + public Collection convertFrom(File file) { + try { + YamlContract yamlContract = new Yaml().loadAs(new FileInputStream(file), YamlContract.class) + return [Contract.make { + request { + method(yamlContract?.request?.method) + url(yamlContract?.request?.url) + headers { + yamlContract?.request?.headers?.each { String key, Object value -> + header(key, value) + } + } + body(yamlContract?.request?.body) + } + response { + status(yamlContract?.response?.status) + headers { + yamlContract?.response?.headers?.each { String key, Object value -> + header(key, value) + } + } + body(yamlContract?.response?.body) + } + }] + } + catch (FileNotFoundException e) { + throw new IllegalStateException(e) + } + } + + @Override + public List convertTo(Collection contracts) { + return contracts.collect { Contract contract -> + YamlContract yamlContract = new YamlContract() + yamlContract.request.with { + method = contract?.request?.method?.clientValue + url = contract?.request?.url?.clientValue + headers = (contract?.request?.headers as Headers)?.asStubSideMap() + body = contract?.request?.body?.clientValue as Map + } + yamlContract.response.with { + status = contract?.response?.status?.clientValue as Integer + headers = (contract?.response?.headers as Headers)?.asStubSideMap() + body = contract?.response?.body?.clientValue as Map + } + return yamlContract + } + } +} diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy index 419a01521b..5b0545316d 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/converter/YamlContractConverterSpec.groovy @@ -1,3 +1,19 @@ +/* + * Copyright 2013-2016 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 + * + * http://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.converter import org.springframework.cloud.contract.spec.Contract @@ -16,8 +32,10 @@ class YamlContractConverterSpec extends Specification { given: assert converter.isAccepted(yml) when: - Contract contract = converter.convertFrom(yml) + Collection contracts = converter.convertFrom(yml) then: + contracts.size() == 1 + Contract contract = contracts.first() contract.request.url.clientValue == "/foo" contract.request.method.clientValue == "PUT" contract.request.headers.entries.find { it.name == "foo" && it.clientValue == "bar" } @@ -31,7 +49,7 @@ class YamlContractConverterSpec extends Specification { given: assert converter.isAccepted(yml) and: - Contract contract = Contract.make { + List contracts = [Contract.make { request { url("/foo") method("PUT") @@ -47,10 +65,12 @@ class YamlContractConverterSpec extends Specification { } body([foo2: "bar"]) } - } + }] when: - YamlContract yamlContract = converter.convertTo(contract) + Collection yamlContracts = converter.convertTo(contracts) then: + yamlContracts.size() == 1 + YamlContract yamlContract = yamlContracts.first() yamlContract.request.url == "/foo" yamlContract.request.method == "PUT" yamlContract.request.headers.find { it.key == "foo" && it.value == "bar" } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy index 244799d239..ab307411d6 100755 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy @@ -45,7 +45,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie producer(regex('[a-zA-Z]+')) ), name: 'Jan', - created: $(consumer('2014-02-02 12:23:43'), producer({ currentDate(it) })) + created: $(consumer('2014-02-02 12:23:43'), producer(execute('currentDate($it)'))) ) headers { header 'Content-Type': 'text/plain' @@ -53,7 +53,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual(''' { @@ -98,7 +98,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual(''' { @@ -146,7 +146,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual(''' { @@ -198,7 +198,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual((''' { @@ -245,7 +245,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual(''' { @@ -293,7 +293,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual((''' { @@ -577,7 +577,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual((''' { @@ -632,7 +632,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual((''' { @@ -1020,7 +1020,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual((''' { @@ -1190,7 +1190,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual((''' { @@ -1225,7 +1225,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual((''' { @@ -1273,7 +1273,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual((''' { @@ -1324,7 +1324,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual((''' { @@ -1352,7 +1352,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie @Issue('42') def 'should generate stub without optional parameters'() { when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), contractDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, contractDsl), contractDsl).toWireMockClientStub() then: AssertionUtil.assertThatJsonsAreEqual((''' { @@ -1450,7 +1450,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } String toWireMockClientJsonStub(groovyDsl) { - new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), groovyDsl).toWireMockClientStub() + new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() } @Issue('180') @@ -1473,7 +1473,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), contractDsl).toWireMockClientStub() + String wireMockStub = new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, contractDsl), contractDsl).toWireMockClientStub() then: println wireMockStub AssertionUtil.assertThatJsonsAreEqual((''' @@ -1624,7 +1624,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie } } when: - def json = new WireMockStubStrategy("Test", new ContractMetadata(null, true, 0, null), groovyDsl).toWireMockClientStub() + def json = new WireMockStubStrategy("Test", new ContractMetadata(null, true, 0, null, groovyDsl), groovyDsl).toWireMockClientStub() then: json == '' } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockStubVerifier.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockStubVerifier.groovy index 484d15938b..cfff555e40 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockStubVerifier.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockStubVerifier.groovy @@ -18,6 +18,7 @@ package org.springframework.cloud.contract.verifier.dsl import com.github.tomakehurst.wiremock.matching.RegexPattern import com.github.tomakehurst.wiremock.stubbing.StubMapping +import org.springframework.cloud.contract.spec.Contract import org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockStubStrategy import org.springframework.cloud.contract.verifier.file.ContractMetadata @@ -33,8 +34,8 @@ trait WireMockStubVerifier { assert !mappingDefinition.contains('org.springframework.cloud.contract.spec.internal') } - void stubMappingIsValidWireMockStub(org.springframework.cloud.contract.spec.Contract contractDsl) { - stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null), contractDsl).toWireMockClientStub()) + void stubMappingIsValidWireMockStub(Contract contractDsl) { + stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, contractDsl), contractDsl).toWireMockClientStub()) } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScannerSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScannerSpec.groovy index 541a387c56..aa5e384b81 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScannerSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/file/ContractFileScannerSpec.groovy @@ -83,6 +83,6 @@ class ContractFileScannerSpec extends Specification { then: result.keySet().size() == 1 result.entries().every { it.value.convertedContract } - result.entries().find { it.value.convertedContract.request.method.clientValue == "PUT" } + result.entries().find { it.value.convertedContract.any { it.request.method.clientValue == "PUT" } } } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/ContractVerifierDslConverterSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/ContractVerifierDslConverterSpec.groovy new file mode 100644 index 0000000000..f7980b63d9 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/ContractVerifierDslConverterSpec.groovy @@ -0,0 +1,150 @@ +/* + * Copyright 2013-2016 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 + * + * http://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.util + +import org.springframework.cloud.contract.spec.Contract +import spock.lang.Specification + +/** + * @author Marcin Grzejszczak + */ +class ContractVerifierDslConverterSpec extends Specification { + + URL single = ContractVerifierDslConverterSpec.getResource("/contract.groovy") + File singleContract = new File(single.toURI()) + URL multiple = ContractVerifierDslConverterSpec.getResource("/multiple_contracts.groovy") + File multipleContracts = new File(multiple.toURI()) + URL invalid = ContractVerifierDslConverterSpec.getResource("/contract.yml") + File invalidContract = new File(invalid.toURI()) + + Contract expectedSingleContract = Contract.make { + request { + method('PUT') + headers { + contentType(applicationJson()) + } + body(""" { "status" : "OK" } """) + url("/1") + } + response { + status 200 + body(""" { "status" : "OK" } """) + headers { + contentType(textPlain()) + } + } + } + + List expectedMultipleContracts = (1..2).collect { int index -> + Contract.make { + request { + method('PUT') + headers { + contentType(applicationJson()) + } + body(""" { "status" : "OK" } """) + url("/${index}") + } + response { + status 200 + body(""" { "status" : "OK" } """) + headers { + contentType(textPlain()) + } + } + } + } + + def "should convert file to a Contract"() { + when: + Contract contract = ContractVerifierDslConverter.convert(singleContract) + then: + contract == expectedSingleContract + } + + def "should throw exception when invalid file is parsed"() { + when: + ContractVerifierDslConverter.convert(invalidContract) + then: + thrown(DslParseException) + } + + def "should convert file to a list of Contracts"() { + when: + List contract = ContractVerifierDslConverter.convertAsCollection(multipleContracts) + then: + contract == expectedMultipleContracts + } + + def "should throw exception when invalid text is parsed"() { + when: + ContractVerifierDslConverter.convert(invalidContract.text) + then: + thrown(DslParseException) + } + + def "should convert text to a Contract"() { + when: + Contract contract = ContractVerifierDslConverter.convert(singleContract.text) + then: + contract == expectedSingleContract + } + + def "should convert text to a list of Contracts"() { + when: + Collection contract = ContractVerifierDslConverter.convertAsCollection(multipleContracts.text) + then: + contract == expectedMultipleContracts + } + + def "should throw an exception when an invalid file is parsed"() { + when: + ContractVerifierDslConverter.convertAsCollection(invalidContract.text) + then: + thrown(DslParseException) + } + + def "should throw an exception with file path when an invalid file is parsed"() { + when: + ContractVerifierDslConverter.convertAsCollection(invalidContract) + then: + DslParseException e = thrown(DslParseException) + e.toString().contains("contract.yml") + } + + def "should throw an exception when a non existent file is parsed"() { + when: + ContractVerifierDslConverter.convertAsCollection(new File("/foo/bar/baz.foo")) + then: + DslParseException e = thrown(DslParseException) + e.cause instanceof FileNotFoundException + } + + def "should convert file to a list of Contracts when there's only one declared contract"() { + when: + Collection contract = ContractVerifierDslConverter.convertAsCollection(singleContract) + then: + contract == [expectedSingleContract] + } + + def "should convert text to a list of Contracts when there's only one declared contract"() { + when: + Collection contract = ContractVerifierDslConverter.convertAsCollection(singleContract.text) + then: + contract == [expectedSingleContract] + } +} diff --git a/spring-cloud-contract-verifier/src/test/resources/META-INF/spring.factories b/spring-cloud-contract-verifier/src/test/resources/META-INF/spring.factories new file mode 100644 index 0000000000..f69e06c844 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/META-INF/spring.factories @@ -0,0 +1,3 @@ +# Converters +org.springframework.cloud.contract.spec.ContractConverter=\ +org.springframework.cloud.contract.verifier.converter.YamlContractConverter \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/contract.groovy b/spring-cloud-contract-verifier/src/test/resources/contract.groovy new file mode 100644 index 0000000000..9d84157ee9 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/contract.groovy @@ -0,0 +1,35 @@ +import org.springframework.cloud.contract.spec.Contract + +/* + * Copyright 2013-2016 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 + * + * http://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. + */ + +Contract.make { + request { + method('PUT') + headers { + contentType(applicationJson()) + } + body(""" { "status" : "OK" } """) + url("/1") + } + response { + status 200 + body(""" { "status" : "OK" } """) + headers { + contentType(textPlain()) + } + } +} diff --git a/spring-cloud-contract-verifier/src/test/resources/multiple_contracts.groovy b/spring-cloud-contract-verifier/src/test/resources/multiple_contracts.groovy new file mode 100644 index 0000000000..db131661ac --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/multiple_contracts.groovy @@ -0,0 +1,36 @@ +import org.springframework.cloud.contract.spec.Contract + +/* + * Copyright 2013-2016 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 + * + * http://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. + */ +(1..2).collect { int index -> + Contract.make { + request { + method('PUT') + headers { + contentType(applicationJson()) + } + body(""" { "status" : "OK" } """) + url("/${index}") + } + response { + status 200 + body(""" { "status" : "OK" } """) + headers { + contentType(textPlain()) + } + } + } +} diff --git a/tests/spring-cloud-contract-stub-runner-integration/README.adoc b/tests/spring-cloud-contract-stub-runner-integration/README.adoc index 9bf476811b..3160b570a9 100644 --- a/tests/spring-cloud-contract-stub-runner-integration/README.adoc +++ b/tests/spring-cloud-contract-stub-runner-integration/README.adoc @@ -67,7 +67,7 @@ and the following Spring Integration Route: [source,xml] ---- -include::src/test/resources/integration-context.xml[] +include::src/test/resources/integration-context.xml[lines=1;18..-1] ----