From b48d50edcc4cd59faae5796c764b45dbd035676b Mon Sep 17 00:00:00 2001 From: Olga Maciaszek-Sharma Date: Thu, 19 Jul 2018 15:03:42 +0200 Subject: [PATCH] Add junit5 support (#690) * Refactoring: extract class building methods. * Move imports to import providers. * Switch to new TestFramework implementation with TestFrameworkDefinition delegate. Handle ignoring tests correctly in JUnit5. * Implement handling JUnit5 rules. * Add tests for JUNIT5. * Update docs. fixes gh-489 --- .../main/asciidoc/verifier_introduction.adoc | 6 +- .../src/main/asciidoc/verifier_messaging.adoc | 4 +- docs/src/main/asciidoc/verifier_setup.adoc | 8 +- .../maven/verifier/GenerateTestsMojo.java | 2 + spring-cloud-contract-verifier/pom.xml | 4 + .../verifier/builder/ClassBuilder.groovy | 28 +- .../JUnitMessagingMethodBodyBuilder.groovy | 7 +- .../verifier/builder/JavaTestGenerator.groovy | 101 ++--- .../verifier/builder/MethodBuilder.groovy | 23 +- .../builder/imports/BaseImportProvider.groovy | 62 +++ .../builder/imports/HttpImportProvider.groovy | 76 ++++ .../builder/imports/ImportDefinitions.groovy | 22 ++ .../imports/MessagingImportProvider.groovy | 32 ++ .../verifier/config/TestFramework.groovy | 123 +++--- .../config/framework/CustomDefinition.groovy | 69 ++++ .../config/framework/JUnit5Definition.groovy | 69 ++++ .../config/framework/JUnitDefinition.groovy | 69 ++++ .../config/framework/SpockDefinition.groovy | 69 ++++ .../framework/TestFrameworkDefinition.groovy | 75 ++++ .../verifier/GeneratorScannerSpec.groovy | 8 +- .../builder/SingleTestGeneratorSpec.groovy | 363 ++++++++++-------- 21 files changed, 940 insertions(+), 280 deletions(-) create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/BaseImportProvider.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/HttpImportProvider.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/ImportDefinitions.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/MessagingImportProvider.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/CustomDefinition.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/JUnit5Definition.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/JUnitDefinition.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/SpockDefinition.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/TestFrameworkDefinition.groovy diff --git a/docs/src/main/asciidoc/verifier_introduction.adoc b/docs/src/main/asciidoc/verifier_introduction.adoc index d5c36e7f29..be760da0a6 100644 --- a/docs/src/main/asciidoc/verifier_introduction.adoc +++ b/docs/src/main/asciidoc/verifier_introduction.adoc @@ -15,7 +15,7 @@ produced by Spring Cloud Contract Verifier. * Messaging routes, if you're using a messaging service. We integrate with Spring Integration, Spring Cloud Stream, Spring AMQP, and Apache Camel. You can also set your own integrations. -* Acceptance tests (in JUnit or Spock) are used to verify if server-side implementation +* Acceptance tests (in JUnit 4, JUnit 5 or Spock) are used to verify if server-side implementation of the API is compliant with the contract (__server tests__). A full test is generated by Spring Cloud Contract Verifier. @@ -363,8 +363,8 @@ mode for HTTP contracts. However, JAX-RX client and explicit HTTP invocations ca used. (To do so, change the `testMode` property of the plugin to `JAX-RS` or `EXPLICIT`, respectively.) -Apart from the default JUnit, you can instead use Spock tests, by setting the plugin -`testFramework` property to `Spock`. +Apart from the default JUnit 4, you can instead use JUnit 5 or Spock tests, by setting the plugin +`testFramework` property to either `JUNIT5` or `Spock`. TIP: You can now also generate WireMock scenarios based on the contracts, by including an order number followed by an underscore at the beginning of the contract file names. diff --git a/docs/src/main/asciidoc/verifier_messaging.adoc b/docs/src/main/asciidoc/verifier_messaging.adoc index 9d4432f756..811353d1ff 100644 --- a/docs/src/main/asciidoc/verifier_messaging.adoc +++ b/docs/src/main/asciidoc/verifier_messaging.adoc @@ -69,8 +69,8 @@ messaging configuration, so you only need the one annotation. === Publisher-Side Test Generation Having the `input` or `outputMessage` sections in your DSL results in creation of tests -on the publisher's side. By default, JUnit tests are created. However, there is also a -possibility to create Spock tests. +on the publisher's side. By default, JUnit 4 tests are created. However, there is also a +possibility to create JUnit 5 or Spock tests. There are 3 main scenarios that we should take into consideration: diff --git a/docs/src/main/asciidoc/verifier_setup.adoc b/docs/src/main/asciidoc/verifier_setup.adoc index 5b91f9dc64..9b3f913cbc 100644 --- a/docs/src/main/asciidoc/verifier_setup.adoc +++ b/docs/src/main/asciidoc/verifier_setup.adoc @@ -245,8 +245,8 @@ from the Groovy DSL should be placed. By default its value is `$buildDir/generated-test-sources/contractVerifier`. * *stubsOutputDir*: Specifies the directory where the generated WireMock stubs from the Groovy DSL should be placed. -* *targetFramework*: Specifies the target test framework to be used. Currently, Spock and -JUnit are supported with JUnit being the default framework. +* *targetFramework*: Specifies the target test framework to be used. Currently, Spock, JUnit 4 (`TestFramework.JUNIT` and +JUnit 5 are supported with JUnit 4 being the default framework. * *contractsProperties*: a map containing properties to be passed to Spring Cloud Contract components. Those properties might be used by e.g. inbuilt or custom Stub Downloaders. @@ -582,8 +582,8 @@ classes. use Spock classes, the class is `spock.lang.Specification`. * *contractsDirectory*: Specifies a directory containing contracts written with the GroovyDSL. The default directory is `/src/test/resources/contracts`. -* *testFramework*: Specifies the target test framework to be used. Currently, Spock and -JUnit are supported with JUnit being the default framework +* *testFramework*: Specifies the target test framework to be used. Currently, Spock, JUnit 4 (`TestFramework.JUNIT` and +6JUnit 5 are supported with JUnit 4 being the default framework. * *packageWithBaseClasses*: Defines a package where all the base classes reside. This setting takes precedence over *baseClassForTests*. The convention is such that, if you have a contract under (for example) `src/test/resources/contract/foo/bar/baz/` and set diff --git a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/GenerateTestsMojo.java b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/GenerateTestsMojo.java index 4c466b7405..56ee9826c0 100644 --- a/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/GenerateTestsMojo.java +++ b/spring-cloud-contract-tools/spring-cloud-contract-maven-plugin/src/main/java/org/springframework/cloud/contract/maven/verifier/GenerateTestsMojo.java @@ -21,6 +21,7 @@ import java.net.URL; import java.util.HashMap; import java.util.List; import java.util.Map; + import javax.inject.Inject; import org.apache.maven.model.Dependency; @@ -33,6 +34,7 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.maven.plugins.annotations.ResolutionScope; import org.apache.maven.project.MavenProject; import org.eclipse.aether.RepositorySystemSession; + import org.springframework.cloud.contract.maven.verifier.stubrunner.AetherStubDownloaderFactory; import org.springframework.cloud.contract.spec.ContractVerifierException; import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties; diff --git a/spring-cloud-contract-verifier/pom.xml b/spring-cloud-contract-verifier/pom.xml index 99b624a210..398a96c486 100644 --- a/spring-cloud-contract-verifier/pom.xml +++ b/spring-cloud-contract-verifier/pom.xml @@ -128,6 +128,10 @@ spring-mock-mvc test + + org.junit.jupiter + junit-jupiter-api + org.springframework.boot spring-boot-starter-jersey diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilder.groovy index 12a6f66799..1f99951cf7 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilder.groovy @@ -18,9 +18,10 @@ package org.springframework.cloud.contract.verifier.builder import groovy.transform.CompileStatic import groovy.transform.PackageScope + +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties import org.springframework.cloud.contract.verifier.config.TestFramework import org.springframework.cloud.contract.verifier.util.NamesUtil -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties /** * Builds a class. Adds all the imports, static imports etc. @@ -104,11 +105,16 @@ class ClassBuilder { return this } - ClassBuilder addImport(List importsToAdd) { + ClassBuilder addImports(List importsToAdd) { imports.addAll(importsToAdd) return this } + ClassBuilder addStaticImports(List importsToAdd) { + staticImports.addAll(importsToAdd) + return this + } + ClassBuilder addStaticImport(String importToAdd) { staticImports << importToAdd return this @@ -124,13 +130,6 @@ class ClassBuilder { return this } - private String appendColonIfJUniTest(String field) { - if (lang == TestFramework.JUNIT && !field.endsWith(';')) { - return "$field;" - } - return field - } - ClassBuilder addField(List fieldsToAdd) { fields.addAll(fieldsToAdd.collect { appendColonIfJUniTest(it) }) return this @@ -202,4 +201,15 @@ class ClassBuilder { 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(';') + } } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy index 20a0d34a12..36b81107ed 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy @@ -16,9 +16,12 @@ 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 @@ -29,8 +32,6 @@ import org.springframework.cloud.contract.spec.internal.NotToEscapePattern import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties import org.springframework.cloud.contract.verifier.util.MapConverter -import java.util.regex.Pattern - import static groovy.json.StringEscapeUtils.escapeJava import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT @@ -195,7 +196,7 @@ class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { protected String getInputString() { String request = 'ContractVerifierMessage inputMessage = contractVerifierMessaging.create(' if (inputMessage.messageBody) { - request = "${request}\n\t\t\t\t\"${StringEscapeUtils.escapeJava(bodyAsString)}\"\n" + request = "${request}\n\t\t\t\t\"${escapeJava(bodyAsString)}\"\n" } if (inputMessage.messageHeaders) { request = "${request}\t\t\t\t, headers()" 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 c3de1c34a7..b6c09026c6 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 @@ -16,20 +16,25 @@ package org.springframework.cloud.contract.verifier.builder +import java.lang.invoke.MethodHandles + import groovy.transform.Canonical 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.config.TestFramework -import org.springframework.cloud.contract.verifier.config.TestMode import org.springframework.cloud.contract.verifier.file.ContractMetadata -import java.lang.invoke.MethodHandles - +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} * @@ -48,61 +53,39 @@ class JavaTestGenerator implements SingleTestGenerator { @Override String buildClass(ContractVerifierConfigProperties configProperties, Collection listOfFiles, String className, String classPackage, String includedDirectoryRelativePath) { ClassBuilder clazz = ClassBuilder.createClass(capitalize(className), classPackage, configProperties, includedDirectoryRelativePath) - if (configProperties.imports) { configProperties.imports.each { clazz.addImport(it) } } - if (configProperties.staticImports) { configProperties.staticImports.each { clazz.addStaticImport(it) } } - if (isScenarioClass(listOfFiles)) { - clazz.addImport(configProperties.targetFramework.getOrderAnnotationImport()) + clazz.addImports(configProperties.targetFramework.getOrderAnnotationImports()) clazz.addClassLevelAnnotation(configProperties.targetFramework.getOrderAnnotation()) } - addJsonPathRelatedImports(clazz) + processContractFiles(listOfFiles, configProperties, clazz) + return clazz.build() + } + private void processContractFiles(Collection listOfFiles, + ContractVerifierConfigProperties configProperties, ClassBuilder clazz) { Map contracts = mapContractsToTheirTestTypes(listOfFiles) - 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}]") - } boolean conditionalImportsAdded = false - boolean toIgnore = listOfFiles.ignored.find { it } - contracts.each { ParsedDsl key, TestType value -> + boolean toIgnore = listOfFiles.ignored.find {it} + contracts.each {ParsedDsl key, TestType value -> if (!conditionalImportsAdded) { + clazz.addImports(getImports(configProperties.targetFramework)) + clazz.addStaticImports(getStaticImports(configProperties.targetFramework)) if (contracts.values().contains(TestType.HTTP)) { - if (configProperties.testMode == TestMode.JAXRSCLIENT) { - clazz.addStaticImport('javax.ws.rs.client.Entity.*') - if (configProperties.targetFramework == TestFramework.JUNIT) { - clazz.addImport('javax.ws.rs.core.Response') - } - } else if (configProperties.testMode == TestMode.MOCKMVC) { - clazz.addStaticImport("${restAssuredPackage}.module.mockmvc.RestAssuredMockMvc.*") - } else { - clazz.addStaticImport("${restAssuredPackage}.RestAssured.*") - } + addHttpRelatedEntries(clazz, configProperties) } - if (configProperties.targetFramework == TestFramework.JUNIT) { - if (contracts.values().contains(TestType.HTTP) && configProperties.testMode == TestMode.MOCKMVC) { - clazz.addImport("${restAssuredPackage}.module.mockmvc.specification.MockMvcRequestSpecification") - clazz.addImport("${restAssuredPackage}.response.ResponseOptions") - } else if (contracts.values().contains(TestType.HTTP) && configProperties.testMode == TestMode.EXPLICIT) { - clazz.addImport("${restAssuredPackage}.specification.RequestSpecification") - clazz.addImport("${restAssuredPackage}.response.Response") - } - clazz.addImport('org.junit.Test') - } - clazz.addStaticImport('org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat') if (configProperties.ruleClassForTests) { - clazz.addImport('org.junit.Rule').addRule(configProperties.ruleClassForTests) + addRule(configProperties, clazz) } if (contracts.values().contains(TestType.MESSAGING)) { addMessagingRelatedEntries(clazz) @@ -116,8 +99,31 @@ class JavaTestGenerator implements SingleTestGenerator { if (toIgnore) { clazz.addImport(configProperties.targetFramework.getIgnoreClass()) } + } - return clazz.build() + private void addRule(ContractVerifierConfigProperties configProperties, ClassBuilder clazz) { + clazz.addImport(getRuleImport()) + if (configProperties.targetFramework.annotationLevelRules()) { + clazz.addClassLevelAnnotation(configProperties.targetFramework + .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.targetFramework, configProperties.testMode)) + clazz.addStaticImports(httpImportProvider.getStaticImports(configProperties.targetFramework, configProperties.testMode)) + } + + 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 @@ -159,8 +165,8 @@ class JavaTestGenerator implements SingleTestGenerator { } private void addJsonPathRelatedImports(ClassBuilder clazz) { - clazz.addImport(['com.jayway.jsonpath.DocumentContext', - 'com.jayway.jsonpath.JsonPath', + clazz.addImports(['com.jayway.jsonpath.DocumentContext', + 'com.jayway.jsonpath.JsonPath', ]) if (this.checker.isClassPresent(JSON_ASSERT_CLASS)) { clazz.addStaticImport(JSON_ASSERT_STATIC_IMPORT) @@ -169,16 +175,11 @@ class JavaTestGenerator implements SingleTestGenerator { private void addMessagingRelatedEntries(ClassBuilder clazz) { clazz.addField(['@Inject ContractVerifierMessaging contractVerifierMessaging', - '@Inject ContractVerifierObjectMapper contractVerifierObjectMapper' + '@Inject ContractVerifierObjectMapper contractVerifierObjectMapper' ]) - clazz.addImport([ 'javax.inject.Inject', - 'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper', - 'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage', - 'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging', - ]) - clazz.addStaticImport('org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers') + clazz.addImports(MessagingImportProvider.getImports()) + clazz.addStaticImports(MessagingImportProvider.getStaticImports()) } - } class ClassPresenceChecker { @@ -189,7 +190,7 @@ class ClassPresenceChecker { try { Class.forName(className) return true - } catch (ClassNotFoundException e) { + } catch (ClassNotFoundException ignored) { if (log.isDebugEnabled()) { log.debug("[${className}] is not present on classpath. Will not add a static import.") } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilder.groovy index 4984a2e0a0..81641b06ec 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilder.groovy @@ -19,13 +19,17 @@ package org.springframework.cloud.contract.verifier.builder import groovy.transform.CompileStatic import groovy.transform.PackageScope 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.config.TestFramework import org.springframework.cloud.contract.verifier.config.TestMode import org.springframework.cloud.contract.verifier.file.ContractMetadata import org.springframework.cloud.contract.verifier.util.NamesUtil +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.config.TestFramework.SPOCK + /** * Builds a test method. Adds an ignore annotation on a method if necessary. * @@ -57,7 +61,7 @@ class MethodBuilder { if (log.isDebugEnabled()) { log.debug("Stub content Groovy DSL [$stubContent]") } - String methodName = methodName(contract, stubsFile, stubContent) + String methodName = MethodBuilder.methodName(contract, stubsFile, stubContent) return new MethodBuilder(methodName, stubContent, configProperties, contract.ignored || stubContent.ignored) } @@ -91,11 +95,11 @@ class MethodBuilder { * Appends to the {@link BlockBuilder} the contents of the test */ void appendTo(BlockBuilder blockBuilder) { - if (configProperties.targetFramework == TestFramework.JUNIT) { + if (isJUnitType()) { blockBuilder.addLine('@Test') } if (ignored) { - blockBuilder.addLine('@Ignore') + blockBuilder.addLine(configProperties.targetFramework.ignoreAnnotation) } blockBuilder.addLine(configProperties.targetFramework.methodModifier + "validate_$methodName() throws Exception {") getMethodBodyBuilder().appendTo(blockBuilder) @@ -104,26 +108,29 @@ class MethodBuilder { private MethodBodyBuilder getMethodBodyBuilder() { if (stubContent.input || stubContent.outputMessage) { - if (configProperties.targetFramework == TestFramework.JUNIT) { + if (isJUnitType()) { return new JUnitMessagingMethodBodyBuilder(stubContent, configProperties) } return new SpockMessagingMethodBodyBuilder(stubContent, configProperties) } if (configProperties.testMode == TestMode.JAXRSCLIENT) { - if (configProperties.targetFramework == TestFramework.JUNIT) { + if (isJUnitType()) { return new JaxRsClientJUnitMethodBodyBuilder(stubContent, configProperties) } return new JaxRsClientSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties) } else if (configProperties.testMode == TestMode.EXPLICIT) { - if (configProperties.targetFramework == TestFramework.JUNIT) { + if (isJUnitType()) { return new ExplicitJUnitMethodBodyBuilder(stubContent, configProperties) } // in Groovy we're using def so we don't have to update the imports return new MockMvcSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties) - } else if (configProperties.targetFramework == TestFramework.SPOCK) { + } else if (configProperties.targetFramework == SPOCK) { return new MockMvcSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties) } return new MockMvcJUnitMethodBodyBuilder(stubContent, configProperties) } + private boolean isJUnitType() { + return JUNIT == configProperties.targetFramework || JUNIT5 == configProperties.targetFramework + } } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/BaseImportProvider.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/BaseImportProvider.groovy new file mode 100644 index 0000000000..8bb12a0e49 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/BaseImportProvider.groovy @@ -0,0 +1,62 @@ +package org.springframework.cloud.contract.verifier.builder.imports + +import groovy.transform.CompileStatic + +import org.springframework.cloud.contract.verifier.config.TestFramework + +import static org.springframework.cloud.contract.verifier.config.TestFramework.CUSTOM +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.config.TestFramework.SPOCK + +/** + * Provides imports based on test framework. + * + * @author Olga Maciaszek-Sharma + * + * @since 2.1.0 + */ +@CompileStatic +class BaseImportProvider { + + private static final ImportDefinitions GENERAL_IMPORTS = new ImportDefinitions([], [ + 'org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat' + ]) + + private static + final Map TEST_FRAMEWORK_SPECIFIC_IMPORTS = [ + (JUNIT) : new ImportDefinitions(['org.junit.Test']), + (JUNIT5): new ImportDefinitions(['org.junit.jupiter.api.Test']), + (SPOCK) : new ImportDefinitions([]), + (CUSTOM): new ImportDefinitions([])] + + private static final Map RULE_IMPORT = [ + (JUNIT) : 'org.junit.Rule', + (JUNIT5): 'org.junit.jupiter.api.extension.ExtendWith', + (SPOCK) : 'org.junit.Rule', + (CUSTOM): 'org.junit.Rule' + ] + + /** + * Returns list of imports for provided test framework. + * @param testFramework + * @return list of imports + */ + static List getImports(TestFramework testFramework) { + return GENERAL_IMPORTS.imports + TEST_FRAMEWORK_SPECIFIC_IMPORTS.get(testFramework).imports + } + + /** + * Returns list of static imports for provided test framework. + * @param testFramework + * @return + */ + static List getStaticImports(TestFramework testFramework) { + return GENERAL_IMPORTS.staticImports + TEST_FRAMEWORK_SPECIFIC_IMPORTS.get(testFramework).staticImports + } + + static String getRuleImport(TestFramework testFramework) { + return RULE_IMPORT.get(testFramework) + } +} + diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/HttpImportProvider.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/HttpImportProvider.groovy new file mode 100644 index 0000000000..879f204303 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/HttpImportProvider.groovy @@ -0,0 +1,76 @@ +package org.springframework.cloud.contract.verifier.builder.imports + +import org.springframework.cloud.contract.verifier.config.TestFramework +import org.springframework.cloud.contract.verifier.config.TestMode + +import static org.springframework.cloud.contract.verifier.config.TestFramework.CUSTOM +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.config.TestFramework.SPOCK +import static org.springframework.cloud.contract.verifier.config.TestMode.EXPLICIT +import static org.springframework.cloud.contract.verifier.config.TestMode.JAXRSCLIENT +import static org.springframework.cloud.contract.verifier.config.TestMode.MOCKMVC + +/** + * Provides imports based on test framework and test mode. + * + * @author Olga Maciaszek-Sharma + * + * @since 2.1.0 + */ +class HttpImportProvider { + + private final Map TEST_MODE_SPECIFIC_IMPORTS = [ + (JAXRSCLIENT): new ImportDefinitions([], ['javax.ws.rs.client.Entity.*']), + (MOCKMVC) : new ImportDefinitions([], ["${restAssuredPackage}.module.mockmvc.RestAssuredMockMvc.*"]), + (EXPLICIT) : new ImportDefinitions([], ["${restAssuredPackage}.RestAssured.*"])] + + private final Map, ImportDefinitions> FRAMEWORK_AND_TEST_MODE_SPECIFIC_IMPORTS = [ + (new Tuple2(JUNIT, JAXRSCLIENT)) : new ImportDefinitions(['javax.ws.rs.core.Response']), + (new Tuple2(JUNIT5, JAXRSCLIENT)): new ImportDefinitions(['javax.ws.rs.core.Response']), + (new Tuple2(JUNIT, MOCKMVC)) : new ImportDefinitions([ + "${restAssuredPackage}.module.mockmvc.specification.MockMvcRequestSpecification", + "${restAssuredPackage}.response.ResponseOptions"]), + (new Tuple2(JUNIT5, MOCKMVC)) : new ImportDefinitions([ + "${restAssuredPackage}.module.mockmvc.specification.MockMvcRequestSpecification", + "${restAssuredPackage}.response.ResponseOptions"]), + (new Tuple2(JUNIT, EXPLICIT)) : new ImportDefinitions(["${restAssuredPackage}.specification.RequestSpecification", + "${restAssuredPackage}.response.Response"]), + (new Tuple2(JUNIT5, EXPLICIT)) : new ImportDefinitions(["${restAssuredPackage}.specification.RequestSpecification", + "${restAssuredPackage}.response.Response"]), + (new Tuple2(SPOCK, JAXRSCLIENT)) : new ImportDefinitions([]), + (new Tuple2(CUSTOM, JAXRSCLIENT)): new ImportDefinitions([]), + (new Tuple2(SPOCK, MOCKMVC)) : new ImportDefinitions([]), + (new Tuple2(CUSTOM, MOCKMVC)) : new ImportDefinitions([]), + (new Tuple2(SPOCK, EXPLICIT)) : new ImportDefinitions([]), + (new Tuple2(CUSTOM, EXPLICIT)) : new ImportDefinitions([]) + ] + + private final String restAssuredPackage + + HttpImportProvider(String restAssuredPackage) { + this.restAssuredPackage = restAssuredPackage + } + + /** + * Returns list of imports for http test contracts for provided test framework and test mode. + * @param testFramework + * @param testMode + * @return list of imports + */ + List getImports(TestFramework testFramework, TestMode testMode) { + return TEST_MODE_SPECIFIC_IMPORTS.get(testMode).imports + + FRAMEWORK_AND_TEST_MODE_SPECIFIC_IMPORTS.get(new Tuple2(testFramework, testMode)).imports + } + + /** + * Returns list of static imports for http test contracts for provided test framework and test mode. + * @param testFramework + * @param testMode + * @return list of static imports + */ + List getStaticImports(TestFramework testFramework, TestMode testMode) { + return TEST_MODE_SPECIFIC_IMPORTS.get(testMode).staticImports + + FRAMEWORK_AND_TEST_MODE_SPECIFIC_IMPORTS.get(new Tuple2(testFramework, testMode)).staticImports + } +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/ImportDefinitions.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/ImportDefinitions.groovy new file mode 100644 index 0000000000..7fb4fe1f8f --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/ImportDefinitions.groovy @@ -0,0 +1,22 @@ +package org.springframework.cloud.contract.verifier.builder.imports + +import groovy.transform.CompileStatic +import groovy.transform.PackageScope + +/** + * @author Olga Maciaszek-Sharma + * + * @since 2.1.0 + */ +@CompileStatic +@PackageScope +class ImportDefinitions { + + final List imports + final List staticImports + + ImportDefinitions(List imports, List staticImports = []) { + this.imports = imports + this.staticImports = staticImports + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/MessagingImportProvider.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/MessagingImportProvider.groovy new file mode 100644 index 0000000000..49897b3f0a --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/imports/MessagingImportProvider.groovy @@ -0,0 +1,32 @@ +package org.springframework.cloud.contract.verifier.builder.imports + +import groovy.transform.CompileStatic + +/** + * Provides imports based on test framework and test mode. + * + * @author Olga Maciaszek-Sharma + * + * @since 2.1.0 + */ +@CompileStatic +class MessagingImportProvider { + + /** + * @return list of imports for messaging test contracts. + */ + static List getImports() { + return ['javax.inject.Inject', + 'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper', + 'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage', + 'org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging', + ] + } + + /** + * @return list of static imports for messaging test contracts. + */ + static List getStaticImports() { + return ['org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers'] + } +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/TestFramework.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/TestFramework.groovy index c223bcb6db..c68035fc5a 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/TestFramework.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/TestFramework.groovy @@ -16,68 +16,105 @@ package org.springframework.cloud.contract.verifier.config +import org.springframework.cloud.contract.verifier.config.framework.CustomDefinition +import org.springframework.cloud.contract.verifier.config.framework.JUnit5Definition +import org.springframework.cloud.contract.verifier.config.framework.JUnitDefinition +import org.springframework.cloud.contract.verifier.config.framework.SpockDefinition +import org.springframework.cloud.contract.verifier.config.framework.TestFrameworkDefinition + /** * Contains main building blocks for a test class for the given framework * * @author Jakub Kubrynski, codearte.io + * @author Olga Maciaszek-Sharma * * @since 1.0.0 */ enum TestFramework { - JUNIT("public ", "public void ", ";", ".java", "Test", "org.junit.Ignore", ["org.junit.FixMethodOrder", "org.junit.runners.MethodSorters"], "@FixMethodOrder(MethodSorters.NAME_ASCENDING)"), - SPOCK("", "def ", "", ".groovy", "Spec", "spock.lang.Ignore", ["spock.lang.Stepwise"], "@Stepwise"), - CUSTOM("", "", "", "", "", "", [], "") - private final String classModifier - private final String methodModifier - private final String lineSuffix - private final String classExtension - private final String classNameSuffix - private final String ignoreClass - private final List orderAnnotationImports - private final String orderAnnotation + SPOCK(new SpockDefinition()), + JUNIT(new JUnitDefinition()), + JUNIT5(new JUnit5Definition()), + CUSTOM(new CustomDefinition()) + @Delegate + private final TestFrameworkDefinition testFrameworkDefinition + + + TestFramework(TestFrameworkDefinition testFrameworkDefinition) { + this.testFrameworkDefinition = testFrameworkDefinition + } + + /** + * @deprecated use {@link #TestFramework(TestFrameworkDefinition)} + * @param classModifier + * @param methodModifier + * @param lineSuffix + * @param classExtension + * @param classNameSuffix + * @param ignoreClass + * @param orderAnnotationImports + * @param orderAnnotation + */ + @Deprecated TestFramework(String classModifier, String methodModifier, String lineSuffix, String classExtension, String classNameSuffix, String ignoreClass, List orderAnnotationImports, String orderAnnotation) { - this.classModifier = classModifier - this.lineSuffix = lineSuffix - this.methodModifier = methodModifier - this.classExtension = classExtension - this.classNameSuffix = classNameSuffix - this.ignoreClass = ignoreClass - this.orderAnnotationImports = orderAnnotationImports - this.orderAnnotation = orderAnnotation - } + testFrameworkDefinition = new TestFrameworkDefinition() { - String getClassModifier() { - return classModifier - } + @Override + String getClassModifier() { + return classModifier + } - String getMethodModifier() { - return methodModifier - } + @Override + String getMethodModifier() { + return methodModifier + } - String getLineSuffix() { - return lineSuffix - } + @Override + String getLineSuffix() { + return lineSuffix + } - String getClassExtension() { - return classExtension - } + @Override + String getClassExtension() { + return classExtension + } - String getClassNameSuffix() { - return classNameSuffix - } + @Override + String getClassNameSuffix() { + return classNameSuffix + } - String getIgnoreClass() { - return ignoreClass - } + @Override + String getIgnoreClass() { + return ignoreClass + } - List getOrderAnnotationImport() { - return orderAnnotationImports - } + @Override + List getOrderAnnotationImports() { + return orderAnnotationImports + } - String getOrderAnnotation() { - return orderAnnotation + @Override + String getOrderAnnotation() { + return orderAnnotation + } + + @Override + String getIgnoreAnnotation() { + return '@Ignore' + } + + @Override + boolean annotationLevelRules() { + return false + } + + @Override + String getRuleAnnotation(String annotationValue) { + throw new UnsupportedOperationException('Not available in framework.') + } + } } } \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/CustomDefinition.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/CustomDefinition.groovy new file mode 100644 index 0000000000..b22ba212ce --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/CustomDefinition.groovy @@ -0,0 +1,69 @@ +package org.springframework.cloud.contract.verifier.config.framework + +import groovy.transform.CompileStatic + +/** + * Defines elements characteristic of Custom test framework to be used during test class construction. + * + * @author Olga Maciaszek-Sharma + * + * @since 2.1.0 + */ +@CompileStatic +class CustomDefinition implements TestFrameworkDefinition { + + @Override + String getClassModifier() { + return '' + } + + @Override + String getMethodModifier() { + return '' + } + + @Override + String getLineSuffix() { + return '' + } + + @Override + String getClassExtension() { + return '' + } + + @Override + String getClassNameSuffix() { + return '' + } + + @Override + String getIgnoreClass() { + return '' + } + + @Override + List getOrderAnnotationImports() { + return [] + } + + @Override + String getOrderAnnotation() { + return '' + } + + @Override + String getIgnoreAnnotation() { + return '@Ignore' + } + + @Override + boolean annotationLevelRules() { + return false + } + + @Override + String getRuleAnnotation(String annotationValue) { + throw new UnsupportedOperationException('Not available in framework.') + } +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/JUnit5Definition.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/JUnit5Definition.groovy new file mode 100644 index 0000000000..79f6d5eec9 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/JUnit5Definition.groovy @@ -0,0 +1,69 @@ +package org.springframework.cloud.contract.verifier.config.framework + +import groovy.transform.CompileStatic + +/** + * Defines elements characteristic of JUnit5 test framework to be used during test class construction. + * + * @author Olga Maciaszek-Sharma + * + * @since 2.1.0 + */ +@CompileStatic +class JUnit5Definition implements TestFrameworkDefinition { + + @Override + String getClassModifier() { + return 'public ' + } + + @Override + String getMethodModifier() { + return 'public void ' + } + + @Override + String getLineSuffix() { + return ';' + } + + @Override + String getClassExtension() { + '.java' + } + + @Override + String getClassNameSuffix() { + return 'Test' + } + + @Override + String getIgnoreClass() { + return 'org.junit.jupiter.api.Disabled' + } + + @Override + List getOrderAnnotationImports() { + throw new UnsupportedOperationException('Not implemented yet in JUnit5 - https://github.com/junit-team/junit5/issues/48') + } + + @Override + String getOrderAnnotation() { + throw new UnsupportedOperationException('Not implemented yet in JUnit5 - https://github.com/junit-team/junit5/issues/48') + } + + @Override + String getIgnoreAnnotation() { + return '@Disabled' + } + + @Override + boolean annotationLevelRules() { + return true + } + + @Override + String getRuleAnnotation(String annotationValue) { + return ("@ExtendWith(${annotationValue}.class)") + } +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/JUnitDefinition.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/JUnitDefinition.groovy new file mode 100644 index 0000000000..f2b6d474fe --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/JUnitDefinition.groovy @@ -0,0 +1,69 @@ +package org.springframework.cloud.contract.verifier.config.framework + +import groovy.transform.CompileStatic + +/** + * Defines elements characteristic of JUnit test framework to be used during test class construction. + * + * @author Olga Maciaszek-Sharma + * + * @since 2.1.0 + */ +@CompileStatic +class JUnitDefinition implements TestFrameworkDefinition { + + @Override + String getClassModifier() { + return 'public ' + } + + @Override + String getMethodModifier() { + return 'public void ' + } + + @Override + String getLineSuffix() { + return ';' + } + + @Override + String getClassExtension() { + return '.java' + } + + @Override + String getClassNameSuffix() { + return 'Test' + } + + @Override + String getIgnoreClass() { + return 'org.junit.Ignore' + } + + @Override + List getOrderAnnotationImports() { + return ['org.junit.FixMethodOrder', 'org.junit.runners.MethodSorters'] + } + + @Override + String getOrderAnnotation() { + return '@FixMethodOrder(MethodSorters.NAME_ASCENDING)' + } + + @Override + String getIgnoreAnnotation() { + return '@Ignore' + } + + @Override + boolean annotationLevelRules() { + return false + } + + @Override + String getRuleAnnotation(String annotationValue) { + throw new UnsupportedOperationException('Not available in JUnit.') + } +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/SpockDefinition.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/SpockDefinition.groovy new file mode 100644 index 0000000000..32384a7587 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/SpockDefinition.groovy @@ -0,0 +1,69 @@ +package org.springframework.cloud.contract.verifier.config.framework + +import groovy.transform.CompileStatic + +/** + * Defines elements characteristic of Spock test framework to be used during test class construction. + * + * @author Olga Maciaszek-Sharma + * + * @since 2.1.0 + */ +@CompileStatic +class SpockDefinition implements TestFrameworkDefinition { + + @Override + String getClassModifier() { + return '' + } + + @Override + String getMethodModifier() { + return 'def ' + } + + @Override + String getLineSuffix() { + return '' + } + + @Override + String getClassExtension() { + return '.groovy' + } + + @Override + String getClassNameSuffix() { + return 'Spec' + } + + @Override + String getIgnoreClass() { + return 'spock.lang.Ignore' + } + + @Override + List getOrderAnnotationImports() { + return ['spock.lang.Stepwise'] + } + + @Override + String getOrderAnnotation() { + return '@Stepwise' + } + + @Override + String getIgnoreAnnotation() { + return '@Ignore' + } + + @Override + boolean annotationLevelRules() { + return false + } + + @Override + String getRuleAnnotation(String annotationValue) { + throw new UnsupportedOperationException('Not available in Spock.') + } +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/TestFrameworkDefinition.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/TestFrameworkDefinition.groovy new file mode 100644 index 0000000000..94788716b4 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/config/framework/TestFrameworkDefinition.groovy @@ -0,0 +1,75 @@ +package org.springframework.cloud.contract.verifier.config.framework + +import groovy.transform.CompileStatic + +/** + * Defines elements characteristic of a given test framework to be used during test class construction. + * + * @author Olga Maciaszek-Sharma + * + * @since 2.1.0 + */ +@CompileStatic +interface TestFrameworkDefinition { + + /** + * Returns the class access level modifier. E.g. for Java tests that would mean {@code public} + **/ + String getClassModifier() + + /** + * Returns the method access level modifier along with the return type. + * E.g. for Java tests that would mean {@code public void} + **/ + String getMethodModifier() + + /** + * Returns the characters that should end each line. E.g. for Java tests that would mean {@code ;} + **/ + String getLineSuffix() + + /** + * Returns the file extension. E.g. for Java tests that would be {@code .java} + **/ + String getClassExtension() + + /** + * Returns the test class name suffix. E.g. for JUnit tests that would be {@code Test} + **/ + String getClassNameSuffix() + + /** + * Returns the qualified name of the class used to ignore or disable tests. E.g. for JUnit 4 tests that would + * be {@code org.junit.Ignore} + **/ + String getIgnoreClass() + + /** + * Returns the qualified names of the classes that are used for arranging tests into scenarios. + * E.g. for JUnit 4 tests that would be {@code 'org.junit.FixMethodOrder'}, {@code 'org.junit.runners.MethodSorters'} + **/ + List getOrderAnnotationImports() + + /** + * Returns the annotation used for arranging tests into scenarios. + * E.g. for JUnit test that would be {@code @FixMethodOrder(MethodSorters.NAME_ASCENDING)} + **/ + String getOrderAnnotation() + + /** + * Returns the annotation used for ignoring or disabling tests. E.g. for JUnit tests that would mean {@code @Ignore} + **/ + String getIgnoreAnnotation() + + /** + * Returns a boolean indicating whether an annotation-type rule or extension is being used or not. + * E.g. for JUnit 5 tests that would return {@code true} + **/ + boolean annotationLevelRules() + + /** + * Returns the test rule or extension annotation with the {@annotationValue} passed as an argument. + * E.g. for JUnit 5 tests that could be {@code @ExtendWith(Example.class)} + **/ + String getRuleAnnotation(String annotationValue) +} diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/GeneratorScannerSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/GeneratorScannerSpec.groovy index 300ca595b3..24947a19da 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/GeneratorScannerSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/GeneratorScannerSpec.groovy @@ -16,10 +16,12 @@ package org.springframework.cloud.contract.verifier +import spock.lang.Specification + import org.springframework.cloud.contract.verifier.builder.JavaTestGenerator import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.config.TestFramework -import spock.lang.Specification + +import static org.springframework.cloud.contract.verifier.config.TestFramework.SPOCK class GeneratorScannerSpec extends Specification { @@ -39,7 +41,7 @@ class GeneratorScannerSpec extends Specification { def "should create class with full package"() { given: - ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(targetFramework: TestFramework.SPOCK) + ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(targetFramework: SPOCK) properties.contractsDslDir = new File(this.getClass().getResource("/directory/with/stubs/package").toURI()) TestGenerator testGenerator = new TestGenerator(properties, classGenerator, Stub(FileSaver)) when: diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy index 6d72082b7c..c4f01db2eb 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGeneratorSpec.groovy @@ -18,17 +18,23 @@ package org.springframework.cloud.contract.verifier.builder import org.junit.Rule import org.junit.rules.TemporaryFolder +import spock.lang.Issue +import spock.lang.Specification + import org.springframework.cloud.contract.verifier.TestGenerator import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties +import org.springframework.cloud.contract.verifier.config.TestFramework import org.springframework.cloud.contract.verifier.config.TestMode import org.springframework.cloud.contract.verifier.file.ContractMetadata import org.springframework.cloud.contract.verifier.util.SyntaxChecker import org.springframework.util.StringUtils -import spock.lang.Issue -import spock.lang.Specification 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.config.TestFramework.SPOCK +import static org.springframework.cloud.contract.verifier.config.TestMode.EXPLICIT +import static org.springframework.cloud.contract.verifier.config.TestMode.JAXRSCLIENT +import static org.springframework.cloud.contract.verifier.config.TestMode.MOCKMVC import static org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter.convertAsCollection class SingleTestGeneratorSpec extends Specification { @@ -49,7 +55,6 @@ class SingleTestGeneratorSpec extends Specification { '@FixMethodOrder(MethodSorters.NAME_ASCENDING)', '@Test', '@Ignore', 'import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification;', 'import io.restassured.response.ResponseOptions;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat'] - private static final List explicitJUnitRestAssured2ClassStrings = ['import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;', 'import org.junit.FixMethodOrder;', 'import org.junit.Ignore;', 'import org.junit.Test;', 'import org.junit.runners.MethodSorters;', 'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static com.jayway.restassured.RestAssured.*;', @@ -62,6 +67,34 @@ class SingleTestGeneratorSpec extends Specification { '@FixMethodOrder(MethodSorters.NAME_ASCENDING)', '@Test', '@Ignore', 'import io.restassured.specification.RequestSpecification;', 'import io.restassured.response.Response;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat'] + private static + final List mockMvcJUnit5RestAssured2ClassStrings = ['import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;', + 'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;', + 'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*;', + '@Test', '@Disabled', 'import com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification;', + 'import com.jayway.restassured.response.ResponseOptions;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat'] + private static + final List mockMvcJUnit5RestAssured3ClassStrings = ['import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;', + 'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;', + 'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static io.restassured.module.mockmvc.RestAssuredMockMvc.*;', + '@Test', '@Disabled', 'import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification;', + 'import io.restassured.response.ResponseOptions;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat'] + + private static + final List explicitJUnit5RestAssured2ClassStrings = ['import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;', + 'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;', + 'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static com.jayway.restassured.RestAssured.*;', + '@Test', '@Disabled', 'import com.jayway.restassured.specification.RequestSpecification;', + 'import com.jayway.restassured.response.Response;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat'] + + private static + final List explicitJUnit5RestAssured3ClassStrings = ['import com.jayway.jsonpath.DocumentContext;', 'import com.jayway.jsonpath.JsonPath;', + 'import org.junit.jupiter.api.Disabled;', 'import org.junit.jupiter.api.Test;', + 'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;', 'import static io.restassured.RestAssured.*;', + '@Test', '@Disabled', 'import io.restassured.specification.RequestSpecification;', + 'import io.restassured.response.Response;', 'import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat'] + + private static final List spockClassRestAssured2Strings = ['import com.jayway.jsonpath.DocumentContext', 'import com.jayway.jsonpath.JsonPath', 'import spock.lang.Ignore', 'import spock.lang.Specification', 'import spock.lang.Stepwise', 'import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson', 'import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*', @@ -85,23 +118,23 @@ class SingleTestGeneratorSpec extends Specification { public static final Closure JAVA_ASSERTER = { String classToTest -> String name = Math.abs(new Random().nextInt()) String changedTest = classToTest - .replace("public class Test", "public class Test${name}") - .replace("public class ContractsTest", "public class Test${name}") + .replace('public class Test', "public class Test${name}") + .replace('public class ContractsTest', "public class Test${name}") String fqn = FQN(classToTest) SyntaxChecker.tryToCompileJavaWithoutImports("${fqn}${name}", changedTest) } static String FQN(String classToTest) { - return classToTest.contains("0_1_0_dev_1_uncommitted_d1174dd") ? - "org.springframework.cloud.contract.verifier.tests.com_uscm.dale_api44_spec._0_1_0_dev_1_uncommitted_d1174dd.Test" : - "test.Test" + return classToTest.contains('0_1_0_dev_1_uncommitted_d1174dd') ? + 'org.springframework.cloud.contract.verifier.tests.com_uscm.dale_api44_spec._0_1_0_dev_1_uncommitted_d1174dd.Test' : + 'test.Test' } public static final Closure JAVA_JAXRS_ASSERTER = { String classToTest -> String name = Math.abs(new Random().nextInt()) String changedTest = classToTest - .replace("public class Test {", "public class Test${name} {\njavax.ws.rs.client.WebTarget webTarget;\n") - .replace("public class ContractsTest {", "public class Test${name} {\njavax.ws.rs.client.WebTarget webTarget;\n") + .replace('public class Test {', "public class Test${name} {\njavax.ws.rs.client.WebTarget webTarget;\n") + .replace('public class ContractsTest {', "public class Test${name} {\njavax.ws.rs.client.WebTarget webTarget;\n") String fqn = FQN(classToTest) SyntaxChecker.tryToCompileJavaWithoutImports("${fqn}${name}", changedTest) } @@ -112,11 +145,11 @@ class SingleTestGeneratorSpec extends Specification { def setup() { file = tmpFolder.newFile() - wiriteContract(file) + writeContract(file) } - private wiriteContract(File file) { - file.write(""" + private writeContract(File file) { + file.write(''' org.springframework.cloud.contract.spec.Contract.make { request { method 'PUT' @@ -126,70 +159,72 @@ class SingleTestGeneratorSpec extends Specification { status OK() } } -""") +''') } - def "should build test class for #testFramework"() { + def 'should build test class for #testFramework'() { given: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() properties.targetFramework = testFramework properties.testMode = mode - ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, 2, convertAsCollection(new File("/"),file)) + ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, order, convertAsCollection(new File('/'), file)) contract.ignored >> true - contract.order >> 2 JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract], "test", "test", 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract], 'test', 'test', 'com/foo') then: classStrings.each { assert clazz.contains(it) } and: asserter(clazz) where: - testFramework | mode | classStrings | asserter - JUNIT | TestMode.MOCKMVC | mockMvcJUnitRestAssured3ClassStrings | JAVA_ASSERTER - JUNIT | TestMode.EXPLICIT | explicitJUnitRestAssured3ClassStrings | JAVA_ASSERTER - SPOCK | TestMode.MOCKMVC | spockClassRestAssured3Strings | GROOVY_ASSERTER - SPOCK | TestMode.EXPLICIT | explicitSpockRestAssured3ClassStrings | GROOVY_ASSERTER + testFramework | order | mode | classStrings | asserter + JUNIT | 2 | MOCKMVC | mockMvcJUnitRestAssured3ClassStrings | JAVA_ASSERTER + JUNIT | 2 | TestMode.EXPLICIT | explicitJUnitRestAssured3ClassStrings | JAVA_ASSERTER + JUNIT5 | null | MOCKMVC | mockMvcJUnit5RestAssured3ClassStrings | JAVA_ASSERTER + JUNIT5 | null | TestMode.EXPLICIT | explicitJUnit5RestAssured3ClassStrings | JAVA_ASSERTER + SPOCK | 2 | MOCKMVC | spockClassRestAssured3Strings | GROOVY_ASSERTER + SPOCK | 2 | TestMode.EXPLICIT | explicitSpockRestAssured3ClassStrings | GROOVY_ASSERTER } - def "should build test class for #testFramework when the path contains bizarre signs"() { + def 'should build test class for #testFramework when the path contains bizarre signs'() { given: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() properties.targetFramework = testFramework - properties.basePackageForTests = "org.springframework.cloud.contract.verifier.tests" + properties.basePackageForTests = 'org.springframework.cloud.contract.verifier.tests' and: - File newFolder = tmpFolder.newFolder("META_INF") - File subfolders = new File(newFolder, "/com.uscm/dale_api44_spec/0.1.0_dev.1.uncommitted+d1174dd/contracts/") + File newFolder = tmpFolder.newFolder('META_INF') + File subfolders = new File(newFolder, '/com.uscm/dale_api44_spec/0.1.0_dev.1.uncommitted+d1174dd/contracts/') subfolders.mkdirs() - File newFile = new File(subfolders, "contract.groovy") + File newFile = new File(subfolders, 'contract.groovy') newFile.createNewFile() - wiriteContract(newFile) + writeContract(newFile) properties.contractsDslDir = newFolder properties.generatedTestSourcesDir = newFolder.parentFile when: int size = new TestGenerator(properties).generate() then: size > 0 - asserter(new File(newFolder.parent, "/org/springframework/cloud/contract/verifier/tests/com_uscm/dale_api44_spec/0_1_0_dev_1_uncommitted_d1174dd/${testName}").text) + asserter(new File(newFolder.parent, '/org/springframework/cloud/contract/verifier/tests/com_uscm/dale_api44_spec/0_1_0_dev_1_uncommitted_d1174dd/' + testName).text) where: testFramework | mode | asserter | testName - JUNIT | TestMode.MOCKMVC | JAVA_ASSERTER | "ContractsTest.java" - JUNIT | TestMode.EXPLICIT | JAVA_ASSERTER | "ContractsTest.java" - SPOCK | TestMode.MOCKMVC | GROOVY_ASSERTER | "ContractsSpec.groovy" - SPOCK | TestMode.EXPLICIT | GROOVY_ASSERTER | "ContractsSpec.groovy" + JUNIT | MOCKMVC | JAVA_ASSERTER | 'ContractsTest.java' + JUNIT | TestMode.EXPLICIT | JAVA_ASSERTER | 'ContractsTest.java' + JUNIT5 | MOCKMVC | JAVA_ASSERTER | 'ContractsTest.java' + JUNIT5 | TestMode.EXPLICIT | JAVA_ASSERTER | 'ContractsTest.java' + SPOCK | MOCKMVC | GROOVY_ASSERTER | 'ContractsSpec.groovy' + SPOCK | TestMode.EXPLICIT | GROOVY_ASSERTER | 'ContractsSpec.groovy' } - def "should build test class for #testFramework with Rest Assured 2.x"() { + def 'should build test class for #testFramework with Rest Assured 2.x'() { given: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() properties.targetFramework = testFramework properties.testMode = mode - ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, 2, - convertAsCollection(new File("/"),file) ) + ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, order, + convertAsCollection(new File('/'), file)) contract.ignored >> true - contract.order >> 2 JavaTestGenerator testGenerator = new JavaTestGenerator(checker: new ClassPresenceChecker() { @Override boolean isClassPresent(String className) { @@ -198,25 +233,27 @@ class SingleTestGeneratorSpec extends Specification { }) when: - String clazz = testGenerator.buildClass(properties, [contract], "test", "test", 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract], 'test', 'test', 'com/foo') then: classStrings.each { assert clazz.contains(it) } - clazz.contains("com.jayway.restassured") - !clazz.contains("io.restassured") + clazz.contains('com.jayway.restassured') + !clazz.contains('io.restassured') where: - testFramework | mode | classStrings - JUNIT | TestMode.MOCKMVC | mockMvcJUnitRestAssured2ClassStrings - JUNIT | TestMode.EXPLICIT | explicitJUnitRestAssured2ClassStrings - SPOCK | TestMode.MOCKMVC | spockClassRestAssured2Strings - SPOCK | TestMode.EXPLICIT | explicitSpockRestAssured2ClassStrings + testFramework | order | mode | classStrings + JUNIT | 2 | MOCKMVC | mockMvcJUnitRestAssured2ClassStrings + JUNIT | 2 | TestMode.EXPLICIT | explicitJUnitRestAssured2ClassStrings + JUNIT5 | null | MOCKMVC | mockMvcJUnit5RestAssured2ClassStrings + JUNIT5 | null | TestMode.EXPLICIT | explicitJUnit5RestAssured2ClassStrings + SPOCK | 2 | MOCKMVC | spockClassRestAssured2Strings + SPOCK | 2 | TestMode.EXPLICIT | explicitSpockRestAssured2ClassStrings } - def "should build test class for #testFramework and mode #mode with two files"() { + def 'should build test class for #testFramework and mode #mode with two files'() { given: File file = tmpFolder.newFile() - file.write(""" + file.write(''' org.springframework.cloud.contract.spec.Contract.make { request { method 'PUT' @@ -233,10 +270,10 @@ class SingleTestGeneratorSpec extends Specification { } } } - """) + ''') and: File file2 = tmpFolder.newFile() - file2.write(""" + file2.write(''' org.springframework.cloud.contract.spec.Contract.make { request { method 'PUT' @@ -253,22 +290,22 @@ class SingleTestGeneratorSpec extends Specification { } } } -""") +''') and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() properties.targetFramework = testFramework ContractMetadata contract = new ContractMetadata(file.toPath(), false, 1, null, - convertAsCollection(new File("/"),file) ) + convertAsCollection(new File('/'), file)) contract.ignored >> false and: ContractMetadata contract2 = new ContractMetadata(file2.toPath(), false, 1, null, - convertAsCollection(new File("/"),file2) ) + convertAsCollection(new File('/'), file2)) contract2.ignored >> false and: JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract, contract2], "test", "test", 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract, contract2], 'test', 'test', 'com/foo') then: classStrings.each { clazz.contains(it) } @@ -277,25 +314,26 @@ class SingleTestGeneratorSpec extends Specification { and: textAssertion(clazz) where: - testFramework | mode | classStrings | asserter | textAssertion - JUNIT | TestMode.MOCKMVC | mockMvcJUnitRestAssured3ClassStrings | JAVA_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, "\t\t\tMockMvcRequestSpecification") == 2 } - JUNIT | TestMode.EXPLICIT | explicitJUnitRestAssured3ClassStrings | JAVA_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, "\t\t\tMockMvcRequestSpecification") == 2 } - SPOCK | TestMode.MOCKMVC | spockClassRestAssured3Strings | GROOVY_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, "\t\t\tdef request") == 2 } - SPOCK | TestMode.EXPLICIT | explicitSpockRestAssured2ClassStrings | GROOVY_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, "\t\t\tdef request") == 2 } + testFramework | mode | classStrings | asserter | textAssertion + JUNIT | MOCKMVC | mockMvcJUnitRestAssured3ClassStrings | JAVA_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2} + JUNIT | TestMode.EXPLICIT | explicitJUnitRestAssured3ClassStrings | JAVA_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2} + JUNIT5 | MOCKMVC | mockMvcJUnit5RestAssured3ClassStrings | JAVA_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2} + JUNIT5 | TestMode.EXPLICIT | explicitJUnit5RestAssured3ClassStrings | JAVA_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2} + SPOCK | MOCKMVC | spockClassRestAssured3Strings | GROOVY_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tdef request') == 2} + SPOCK | TestMode.EXPLICIT | explicitSpockRestAssured2ClassStrings | GROOVY_ASSERTER | {String test -> StringUtils.countOccurrencesOf(test, '\t\t\tdef request') == 2} } - def "should build JaxRs test class for #testFramework"() { + def 'should build JaxRs test class for #testFramework'() { given: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() properties.testMode = TestMode.JAXRSCLIENT properties.targetFramework = testFramework - ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, 2, convertAsCollection(new File("/"),file)) + ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, null, convertAsCollection(new File('/'), file)) contract.ignored >> true - contract.order >> 2 JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract], "test", "test", 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract], 'test', 'test', 'com/foo') then: classStrings.each { clazz.contains(it) } @@ -304,15 +342,16 @@ class SingleTestGeneratorSpec extends Specification { asserter(clazz) where: - testFramework | classStrings | asserter - JUNIT | ['import static javax.ws.rs.client.Entity.*', 'import javax.ws.rs.core.Response'] | JAVA_JAXRS_ASSERTER - SPOCK | ['import static javax.ws.rs.client.Entity.*'] | GROOVY_ASSERTER + testFramework | classStrings | asserter + JUNIT | ['import static javax.ws.rs.client.Entity.*', 'import javax.ws.rs.core.Response'] | JAVA_JAXRS_ASSERTER + JUNIT5 | ['import static javax.ws.rs.client.Entity.*', 'import javax.ws.rs.core.Response'] | JAVA_JAXRS_ASSERTER + SPOCK | ['import static javax.ws.rs.client.Entity.*'] | GROOVY_ASSERTER } - def "should work if there is messaging and rest in one folder #testFramework"() { + def 'should work if there is messaging and rest in one folder #testFramework'() { given: File secondFile = tmpFolder.newFile() - secondFile.write(""" + secondFile.write(''' org.springframework.cloud.contract.spec.Contract.make { ignored() label 'some_label' @@ -327,22 +366,20 @@ class SingleTestGeneratorSpec extends Specification { assertThat('hashCode()') } } - """) + ''') and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() properties.targetFramework = testFramework - ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, 2, convertAsCollection(new File("/"),file)) + ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, order, convertAsCollection(new File('/'), file)) contract.ignored >> true - contract.order >> 2 and: - ContractMetadata contract2 = new ContractMetadata(secondFile.toPath(), true, 1, 2, convertAsCollection(new File("/"),secondFile)) + ContractMetadata contract2 = new ContractMetadata(secondFile.toPath(), true, 1, order, convertAsCollection(new File('/'), secondFile)) contract2.ignored >> true - contract2.order >> 2 and: JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract, contract2], "test", "test", 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract, contract2], 'test', 'test', 'com/foo') then: classStrings.each { clazz.contains(it) } @@ -352,16 +389,17 @@ class SingleTestGeneratorSpec extends Specification { asserter(clazz) where: - testFramework | classStrings | asserter - JUNIT | mockMvcJUnitRestAssured3ClassStrings | JAVA_ASSERTER - SPOCK | spockClassRestAssured3Strings | GROOVY_ASSERTER + testFramework | order | classStrings | asserter + JUNIT | 2 | mockMvcJUnitRestAssured3ClassStrings | JAVA_ASSERTER + JUNIT5 | null | mockMvcJUnit5RestAssured3ClassStrings | JAVA_ASSERTER + SPOCK | 2 | spockClassRestAssured3Strings | GROOVY_ASSERTER } @Issue('#30') - def "should ignore a test if the contract is ignored in the dsl"() { + def 'should ignore a test if the contract is ignored in the dsl'() { given: File secondFile = tmpFolder.newFile() - secondFile.write(""" + secondFile.write(''' org.springframework.cloud.contract.spec.Contract.make { ignored() request { @@ -372,37 +410,37 @@ class SingleTestGeneratorSpec extends Specification { status OK() } } - """) + ''') and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() properties.targetFramework = testFramework and: - ContractMetadata contract2 = new ContractMetadata(secondFile.toPath(), true, 1, 2, convertAsCollection(new File("/"),file)) + ContractMetadata contract2 = new ContractMetadata(secondFile.toPath(), true, 1, order, convertAsCollection(new File('/'), file)) contract2.ignored >> false - contract2.order >> 2 and: JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract2], "test", "test", 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract2], 'test', 'test', 'com/foo') then: classStrings.each { clazz.contains(it) } - clazz.contains('@Ignore') + clazz.contains(ignoreAnnotation) and: asserter(clazz) where: - testFramework | classStrings | asserter - JUNIT | mockMvcJUnitRestAssured3ClassStrings | JAVA_ASSERTER - SPOCK | spockClassRestAssured3Strings | GROOVY_ASSERTER + testFramework | order | classStrings | ignoreAnnotation | asserter + JUNIT | 2 | mockMvcJUnitRestAssured3ClassStrings | '@Ignore' | JAVA_ASSERTER + JUNIT5 | null | mockMvcJUnit5RestAssured3ClassStrings | '@Disabled' | JAVA_ASSERTER + SPOCK | 2 | spockClassRestAssured3Strings | '@Ignore' | GROOVY_ASSERTER } @Issue('#117') - def "should generate test in explicit test mode using JUnit"() { + def 'should generate test in explicit test mode using JUnit'() { given: - String baseClass = """ + String baseClass = ''' // tag::context_path_baseclass[] import io.restassured.RestAssured; import org.junit.Before; @@ -421,11 +459,11 @@ class SingleTestGeneratorSpec extends Specification { } } // end::context_path_baseclass[] - """ - SyntaxChecker.tryToCompileJavaWithoutImports("test.ContextPathTestingBaseClass", "package test;\n${baseClass}") + ''' + SyntaxChecker.tryToCompileJavaWithoutImports('test.ContextPathTestingBaseClass', "package test;\n${baseClass}") and: File secondFile = tmpFolder.newFile() - secondFile.write(""" + secondFile.write(''' // tag::context_path_contract[] org.springframework.cloud.contract.spec.Contract.make { request { @@ -437,28 +475,28 @@ class SingleTestGeneratorSpec extends Specification { } } // end::context_path_contract[] - """) + ''') and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() properties.targetFramework = JUNIT properties.testMode = TestMode.EXPLICIT - properties.baseClassForTests = "test.ContextPathTestingBaseClass" + properties.baseClassForTests = 'test.ContextPathTestingBaseClass' and: ContractMetadata contract = new ContractMetadata(file.toPath(), false, 1, - null, convertAsCollection(new File("/"),file)) + null, convertAsCollection(new File('/'), file)) and: SingleTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract], "test", "test", 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract], 'test', 'test', 'com/foo') then: - clazz.contains("RequestSpecification request = given();") - clazz.contains("Response response = given().spec(request)") + clazz.contains('RequestSpecification request = given();') + clazz.contains('Response response = given().spec(request)') } def "should pick the contract's name as the test method"() { given: File secondFile = tmpFolder.newFile() - secondFile.write(""" + secondFile.write(''' org.springframework.cloud.contract.spec.Contract.make { name("MySuperMethod") request { @@ -469,18 +507,18 @@ class SingleTestGeneratorSpec extends Specification { status OK() } } - """) + ''') and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(); properties.targetFramework = testFramework - ContractMetadata contract = new ContractMetadata(secondFile.toPath(), false, 1, null, convertAsCollection(new File("/"),secondFile)) + ContractMetadata contract = new ContractMetadata(secondFile.toPath(), false, 1, null, convertAsCollection(new File('/'), secondFile)) JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract], "test", "test", 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract], 'test', 'test', 'com/foo') then: - clazz.contains("validate_mySuperMethod()") + clazz.contains('validate_mySuperMethod()') where: - testFramework << [JUNIT, SPOCK] + testFramework << [JUNIT, JUNIT5, SPOCK] } def "should pick the contract's name as the test method when there are multiple contracts"() { @@ -505,18 +543,18 @@ class SingleTestGeneratorSpec extends Specification { and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(); properties.targetFramework = testFramework - ContractMetadata contract = new ContractMetadata(secondFile.toPath(), false, 1, null, convertAsCollection(new File("/"),secondFile)) + ContractMetadata contract = new ContractMetadata(secondFile.toPath(), false, 1, null, convertAsCollection(new File('/'), secondFile)) JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract], "test", "test", 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract], 'test', 'test', 'com/foo') then: - clazz.contains("validate_shouldHaveIndex1()") - clazz.contains("validate_shouldHaveIndex2()") + clazz.contains('validate_shouldHaveIndex1()') + clazz.contains('validate_shouldHaveIndex2()') where: - testFramework << [JUNIT, SPOCK] + testFramework << [JUNIT, JUNIT5, SPOCK] } - def "should generate the test method when there are multiple contracts without name field"() { + def 'should generate the test method when there are multiple contracts without name field'() { given: File secondFile = tmpFolder.newFile() secondFile.write(''' @@ -537,26 +575,26 @@ class SingleTestGeneratorSpec extends Specification { and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(); properties.targetFramework = testFramework - ContractMetadata contract = new ContractMetadata(secondFile.toPath(), false, 1, null, convertAsCollection(new File("/"),secondFile)) + ContractMetadata contract = new ContractMetadata(secondFile.toPath(), false, 1, null, convertAsCollection(new File('/'), secondFile)) JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract], "test", "test", 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract], 'test', 'test', 'com/foo') then: - clazz.contains("_0() throws Exception") - clazz.contains("_1() throws Exception") + clazz.contains('_0() throws Exception') + clazz.contains('_1() throws Exception') where: - testFramework << [JUNIT, SPOCK] + testFramework << [JUNIT, JUNIT5, SPOCK] } - @Issue("#359") - def "should generate tests from a contract that references a file for [#testFramework]"() { + @Issue('#359') + def 'should generate tests from a contract that references a file for [#testFramework]'() { given: - File contractLocation = new File(SingleTestGeneratorSpec.class.getResource("/classpath/readFromFile.groovy").toURI()) + File contractLocation = new File(SingleTestGeneratorSpec.class.getResource('/classpath/readFromFile.groovy').toURI()) File temp = tmpFolder.newFolder() and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties( targetFramework: testFramework, contractsDslDir: contractLocation.parentFile, - basePackageForTests: "a.b", + basePackageForTests: 'a.b', generatedTestSourcesDir: temp ) TestGenerator testGenerator = new TestGenerator(properties) @@ -565,22 +603,22 @@ class SingleTestGeneratorSpec extends Specification { then: count == 1 and: - String test = new File(temp, "a/b/ContractVerifier" + (testFramework == JUNIT ? "Test.java" : "Spec.groovy")).text - test.contains("REQUEST") - test.contains("RESPONSE") + String test = new File(temp, "a/b/ContractVerifier${getTestName(testFramework)}").text + test.contains('REQUEST') + test.contains('RESPONSE') where: - testFramework << [JUNIT, SPOCK] + testFramework << [JUNIT, JUNIT5, SPOCK] } - @Issue("#260") - def "should generate tests in a folder taken from basePackageForTests when it is set for [#testFramework]"() { + @Issue('#260') + def 'should generate tests in a folder taken from basePackageForTests when it is set for [#testFramework]'() { given: - File contractLocation = new File(SingleTestGeneratorSpec.class.getResource("/classpath/readFromFile.groovy").toURI()) + File contractLocation = new File(SingleTestGeneratorSpec.class.getResource('/classpath/readFromFile.groovy').toURI()) File temp = tmpFolder.newFolder() and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties( targetFramework: testFramework, contractsDslDir: contractLocation.parentFile, - basePackageForTests: "a.b", generatedTestSourcesDir: temp + basePackageForTests: 'a.b', generatedTestSourcesDir: temp ) TestGenerator testGenerator = new TestGenerator(properties) when: @@ -588,22 +626,22 @@ class SingleTestGeneratorSpec extends Specification { then: count == 1 and: - String test = new File(temp, "a/b/ContractVerifier" + (testFramework == JUNIT ? "Test.java" : "Spec.groovy")).text - test.contains("REQUEST") - test.contains("RESPONSE") + String test = new File(temp, "a/b/ContractVerifier${getTestName(testFramework)}").text + test.contains('REQUEST') + test.contains('RESPONSE') where: - testFramework << [JUNIT, SPOCK] + testFramework << [JUNIT, JUNIT5, SPOCK] } - @Issue("#260") + @Issue('#260') def "should generate tests in a folder taken from baseClassForTests's package when it is set for [#testFramework]"() { given: - File contractLocation = new File(SingleTestGeneratorSpec.class.getResource("/classpath/readFromFile.groovy").toURI()) + File contractLocation = new File(SingleTestGeneratorSpec.class.getResource('/classpath/readFromFile.groovy').toURI()) File temp = tmpFolder.newFolder() and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties( targetFramework: testFramework, contractsDslDir: contractLocation.parentFile, - baseClassForTests: "a.b.SomeClass", generatedTestSourcesDir: temp + baseClassForTests: 'a.b.SomeClass', generatedTestSourcesDir: temp ) TestGenerator testGenerator = new TestGenerator(properties) when: @@ -611,22 +649,22 @@ class SingleTestGeneratorSpec extends Specification { then: count == 1 and: - String test = new File(temp, "a/b/ContractVerifier" + (testFramework == JUNIT ? "Test.java" : "Spec.groovy")).text - test.contains("REQUEST") - test.contains("RESPONSE") + String test = new File(temp, "a/b/ContractVerifier${getTestName(testFramework)}").text + test.contains('REQUEST') + test.contains('RESPONSE') where: - testFramework << [JUNIT, SPOCK] + testFramework << [JUNIT, JUNIT5, SPOCK] } - @Issue("#260") - def "should generate tests in a folder taken from packageWithBaseClasses when it is set for [#testFramework]"() { + @Issue('#260') + def 'should generate tests in a folder taken from packageWithBaseClasses when it is set for [#testFramework]'() { given: - File contractLocation = new File(SingleTestGeneratorSpec.class.getResource("/classpath/readFromFile.groovy").toURI()) + File contractLocation = new File(SingleTestGeneratorSpec.class.getResource('/classpath/readFromFile.groovy').toURI()) File temp = tmpFolder.newFolder() and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties( targetFramework: testFramework, contractsDslDir: contractLocation.parentFile, - packageWithBaseClasses: "a.b", generatedTestSourcesDir: temp + packageWithBaseClasses: 'a.b', generatedTestSourcesDir: temp ) TestGenerator testGenerator = new TestGenerator(properties) when: @@ -634,17 +672,17 @@ class SingleTestGeneratorSpec extends Specification { then: count == 1 and: - String test = new File(temp, "a/b/ContractVerifier" + (testFramework == JUNIT ? "Test.java" : "Spec.groovy")).text - test.contains("REQUEST") - test.contains("RESPONSE") + String test = new File(temp, "a/b/ContractVerifier${getTestName(testFramework)}").text + test.contains('REQUEST') + test.contains('RESPONSE') where: - testFramework << [JUNIT, SPOCK] + testFramework << [JUNIT, JUNIT5, SPOCK] } - @Issue("#260") - def "should generate tests in a default folder when no property was passed for [#testFramework]"() { + @Issue('#260') + def 'should generate tests in a default folder when no property was passed for [#testFramework]'() { given: - File contractLocation = new File(SingleTestGeneratorSpec.class.getResource("/classpath/readFromFile.groovy").toURI()) + File contractLocation = new File(SingleTestGeneratorSpec.class.getResource('/classpath/readFromFile.groovy').toURI()) File temp = tmpFolder.newFolder() and: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties( @@ -657,14 +695,29 @@ class SingleTestGeneratorSpec extends Specification { then: count == 1 and: - String test = new File(temp, "org/springframework/cloud/contract/verifier/tests/ContractVerifier" + (testFramework == JUNIT ? "Test.java" : "Spec.groovy")).text - test.contains("REQUEST") - test.contains("RESPONSE") + String test = new File(temp, "org/springframework/cloud/contract/verifier/tests/ContractVerifier${getTestName(testFramework)}").text + test.contains('REQUEST') + test.contains('RESPONSE') where: - testFramework << [JUNIT, SPOCK] + testFramework << [JUNIT, JUNIT5, SPOCK] } + def 'should throw exception in JUnit5 when contract belongs to scenario'() { + given: + ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() + properties.targetFramework = JUNIT5 + properties.testMode = mode + ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, 1, convertAsCollection(new File('/'), file)) + JavaTestGenerator testGenerator = new JavaTestGenerator() + when: + testGenerator.buildClass(properties, [contract], 'test', 'test', 'com/foo') + then: + thrown(UnsupportedOperationException) + where: + mode << [MOCKMVC, EXPLICIT, JAXRSCLIENT] + } - - + private static String getTestName(TestFramework testFramework) { + testFramework == SPOCK ? 'Spec.groovy' : 'Test.java' + } }