From 972a50265f5d1d3558284d258c625be029090fbb Mon Sep 17 00:00:00 2001 From: Marcin Grzejszczak Date: Thu, 27 Jun 2019 23:01:37 +0200 Subject: [PATCH] Refactored class and method generation (#1116) following two event storming sessions with @pilloPl and @OlgaMaciaszek and the Spring Cloud Contract community we've decided to refactor the core modules of Spring Cloud Contract Verifier. The main idea is that the current `JavaTestGenerator`'s implementation no longer uses complex logic to generate classes and methods. We've introduced abstractions such as: - class body builder (to build classes) - groovy and java class metadata - imports (for various frameworks) - default setup for json, xml, restassured, jaxrs - class annotations for spock, junit and junit5 - field insertion e.g. for messaging --- docs/src/main/asciidoc/verifier_contract.adoc | 2 +- .../contract/spec/internal/Cookies.groovy | 8 + .../contract/spec/internal/Headers.groovy | 8 +- .../spec/internal/RegexProperty.groovy | 27 +- .../RecursiveFilesConverterSpec.groovy | 10 + .../_request_request.json | 3 + .../_request_request.pdf | Bin 0 -> 14631 bytes spring-cloud-contract-verifier/pom.xml | 19 + .../contract/verifier/TestGenerator.groovy | 1 - .../contract/verifier/builder/Acceptor.java | 23 + .../verifier/builder/BaseClassProvider.java | 80 + .../verifier/builder/BlockBuilder.groovy | 114 +- .../builder/BodyAssertionLineCreator.java | 130 ++ .../builder/BodyMethodGeneration.groovy | 92 -- .../builder/BodyMethodGeneration.java | 84 + .../verifier/builder/BodyMethodVisitor.java | 142 ++ .../contract/verifier/builder/BodyParser.java | 164 ++ .../contract/verifier/builder/BodyReader.java | 90 ++ .../contract/verifier/builder/BodyThen.java | 37 + .../verifier/builder/ClassAnnotation.java | 21 + .../builder/ClassAnnotationsBuilder.java | 55 + .../verifier/builder/ClassBodyBuilder.java | 94 ++ .../verifier/builder/ClassBuilder.groovy | 232 --- .../verifier/builder/ClassMetaData.java | 35 + .../verifier/builder/ClassVerifier.java | 30 + ...tionType.groovy => CommunicationType.java} | 11 +- .../verifier/builder/ComparisonBuilder.java | 104 ++ .../verifier/builder/ContentHelper.java | 54 + .../builder/CookieElementProcessor.java | 85 + .../verifier/builder/CustomImports.java | 46 + .../verifier/builder/CustomStaticImports.java | 47 + .../builder/DefaultBaseClassProvider.java | 34 + .../builder/DefaultClassMetadata.java | 44 + .../verifier/builder/DefaultImports.java | 60 + .../builder/DefaultJsonStaticImports.java | 52 + .../builder/DefaultStaticImports.java | 45 + .../verifier/builder/ExplicitAcceptor.java | 27 + .../ExplicitJUnitMethodBodyBuilder.groovy | 52 - .../builder/ExplicitRequestGiven.java | 43 + .../builder/ExplicitResponseWhen.java | 43 + .../builder/ExplicitRestAssuredImports.java | 58 + .../ExplicitRestAssuredStaticImports.java | 56 + .../contract/verifier/builder/Field.java | 21 + .../verifier/builder/FieldBuilder.java | 42 + .../GeneratedClassDataForMethod.groovy | 47 - .../builder/GeneratedClassDataForMethod.java | 64 + .../builder/GeneratedClassMetaData.java | 84 + ...erifier.groovy => GeneratedTestClass.java} | 31 +- .../builder/GeneratedTestClassBuilder.java | 182 +++ .../builder/GenericBinaryBodyThen.java | 64 + .../verifier/builder/GenericHttpBodyThen.java | 75 + .../verifier/builder/GenericJsonBodyThen.java | 220 +++ .../verifier/builder/GenericTextBodyThen.java | 79 + .../verifier/builder/GenericXmlBodyThen.java | 56 + .../contract/verifier/builder/Given.java | 21 + .../verifier/builder/GroovyBodyParser.java | 88 + .../verifier/builder/GroovyClassMetaData.java | 108 ++ .../builder/GroovyComparisonBuilder.java | 68 + ...kMethodRequestProcessingBodyBuilder.groovy | 143 -- .../contract/verifier/builder/Imports.java | 21 + .../verifier/builder/ImportsBuilder.java | 105 ++ .../verifier/builder/JUnit4IgnoreImports.java | 50 + .../builder/JUnit4IgnoreMethodAnnotation.java | 52 + .../verifier/builder/JUnit4Imports.java | 50 + .../builder/JUnit4MethodAnnotation.java | 51 + .../builder/JUnit4OrderClassAnnotation.java | 52 + .../verifier/builder/JUnit4OrderImports.java | 53 + .../verifier/builder/JUnit5IgnoreImports.java | 50 + .../builder/JUnit5IgnoreMethodAnnotation.java | 52 + .../verifier/builder/JUnit5Imports.java | 51 + .../builder/JUnit5MethodAnnotation.java | 51 + .../builder/JUnit5OrderClassAnnotation.java | 51 + .../verifier/builder/JUnit5OrderImports.java | 51 + .../JUnitMessagingMethodBodyBuilder.groovy | 292 ---- .../builder/JUnitMethodBodyBuilder.groovy | 244 --- .../verifier/builder/JUnitMethodMetadata.java | 58 + .../verifier/builder/JavaClassMetaData.java | 103 ++ .../verifier/builder/JavaJaxRsThen.java | 39 + .../verifier/builder/JavaJaxRsWhen.java | 38 + .../builder/JavaMessagingBodyParser.java | 24 + .../verifier/builder/JavaMessagingGiven.java | 38 + .../builder/JavaMessagingWithBodyThen.java | 39 + .../builder/JavaRestAssuredGiven.java | 38 + .../verifier/builder/JavaRestAssuredThen.java | 39 + .../verifier/builder/JavaRestAssuredWhen.java | 38 + .../verifier/builder/JavaTestGenerator.groovy | 232 --- .../verifier/builder/JavaTestGenerator.java | 126 ++ .../verifier/builder/JaxRsAcceptor.java | 30 + .../verifier/builder/JaxRsBodyParser.java | 36 + .../JaxRsClientJUnitMethodBodyBuilder.groovy | 265 --- ...kMethodRequestProcessingBodyBuilder.groovy | 265 --- .../contract/verifier/builder/JaxRsGiven.java | 39 + .../verifier/builder/JaxRsImports.java | 51 + .../builder/JaxRsRequestCookiesWhen.java | 81 + .../builder/JaxRsRequestHeadersWhen.java | 89 ++ .../builder/JaxRsRequestInvokerWhen.java | 40 + .../builder/JaxRsRequestMethodWhen.java | 88 + .../verifier/builder/JaxRsRequestWhen.java | 68 + .../builder/JaxRsResponseCookiesThen.java | 73 + .../builder/JaxRsResponseHeadersThen.java | 96 ++ .../verifier/builder/JaxRsStaticImports.java | 50 + .../verifier/builder/JaxRsStatusCodeThen.java | 48 + .../contract/verifier/builder/JaxRsThen.java | 59 + .../verifier/builder/JaxRsUrlPathWhen.java | 119 ++ .../contract/verifier/builder/JaxRsWhen.java | 74 + .../JsonBodyVerificationBuilder.groovy | 320 ---- .../builder/JsonBodyVerificationBuilder.java | 363 +++++ .../verifier/builder/JsonImports.java | 52 + .../verifier/builder/JsonPathImports.java | 52 + .../builder/MessagingAssertThatThen.java | 41 + .../builder/MessagingAssertThatWhen.java | 41 + .../verifier/builder/MessagingBodyGiven.java | 71 + .../verifier/builder/MessagingBodyParser.java | 43 + .../verifier/builder/MessagingBodyThen.java | 68 + .../verifier/builder/MessagingBodyWhen.java | 42 + .../verifier/builder/MessagingFields.java | 52 + .../verifier/builder/MessagingGiven.java | 64 + .../builder/MessagingHeadersGiven.java | 57 + .../builder/MessagingHeadersThen.java | 108 ++ .../verifier/builder/MessagingImports.java | 54 + .../builder/MessagingMethodBodyBuilder.groovy | 149 -- .../builder/MessagingReceiveMessageThen.java | 64 + .../builder/MessagingSpockNoMessageThen.java | 48 + .../builder/MessagingStaticImports.java | 53 + .../builder/MessagingTriggeredByWhen.java | 42 + .../verifier/builder/MessagingWhen.java | 55 + .../builder/MessagingWithBodyThen.java | 66 + .../verifier/builder/MetaDataBuilder.java | 47 + .../verifier/builder/MethodAcceptor.java | 25 + .../builder/MethodAnnotationBuilder.java | 57 + .../verifier/builder/MethodAnnotations.java | 5 + .../verifier/builder/MethodBodyBuilder.groovy | 642 -------- .../verifier/builder/MethodBuilder.groovy | 152 -- .../verifier/builder/MethodMetadata.java | 35 + .../builder/MethodMetadataBuilder.java | 49 + .../verifier/builder/MethodVisitor.java | 26 + .../verifier/builder/MockMvcAcceptor.java | 30 + .../verifier/builder/MockMvcAsyncWhen.java | 57 + .../verifier/builder/MockMvcBodyGiven.java | 95 ++ .../verifier/builder/MockMvcCookiesGiven.java | 74 + .../verifier/builder/MockMvcHeadersGiven.java | 75 + .../MockMvcJUnitMethodBodyBuilder.groovy | 51 - .../builder/MockMvcMultipartGiven.java | 88 + .../builder/MockMvcQueryParamsWhen.java | 84 + .../verifier/builder/MockMvcRequestGiven.java | 43 + .../verifier/builder/MockMvcResponseWhen.java | 43 + .../builder/MockMvcRestAssuredImports.java | 59 + .../MockMvcRestAssuredStaticImports.java | 56 + .../verifier/builder/MockMvcUrlWhen.java | 69 + .../verifier/builder/NameProvider.java | 82 + .../verifier/builder/OurCallable.java | 23 + .../verifier/builder/QueryParamsResolver.java | 41 + .../RequestProcessingMethodBodyBuilder.groovy | 319 ---- .../builder/RestAssuredBodyParser.java | 34 + .../builder/RestAssuredCookiesThen.java | 61 + .../verifier/builder/RestAssuredGiven.java | 77 + .../builder/RestAssuredHeadersThen.java | 89 ++ .../RestAssuredJUnitMethodBodyBuilder.groovy | 130 -- .../builder/RestAssuredStatusCodeThen.java | 49 + .../verifier/builder/RestAssuredThen.java | 61 + .../verifier/builder/RestAssuredVerifier.java | 61 + .../verifier/builder/RestAssuredWhen.java | 77 + .../verifier/builder/SingleMethodBuilder.java | 203 +++ ...erator.groovy => SingleTestGenerator.java} | 70 +- .../verifier/builder/SpockIgnoreImports.java | 50 + .../builder/SpockIgnoreMethodAnnotation.java | 52 + .../verifier/builder/SpockImports.java | 50 + .../builder/SpockJaxRsBodyParser.java | 40 + .../verifier/builder/SpockJaxRsThen.java | 39 + .../verifier/builder/SpockJaxRsWhen.java | 38 + .../builder/SpockMessagingBodyParser.java | 25 + .../builder/SpockMessagingEmptyThen.java | 49 + .../verifier/builder/SpockMessagingGiven.java | 38 + .../SpockMessagingMethodBodyBuilder.groovy | 286 ---- .../builder/SpockMessagingWithBodyThen.java | 39 + .../verifier/builder/SpockMethodMetadata.java | 57 + ...kMethodRequestProcessingBodyBuilder.groovy | 238 --- .../builder/SpockMockMvcMultipartGiven.java | 88 + .../builder/SpockMockMvcRequestGiven.java | 46 + .../builder/SpockMockMvcResponseWhen.java | 46 + .../builder/SpockOrderClassAnnotation.java | 51 + .../verifier/builder/SpockOrderImports.java | 52 + .../builder/SpockRestAssuredBodyParser.java | 35 + .../builder/SpockRestAssuredGiven.java | 38 + .../builder/SpockRestAssuredThen.java | 39 + .../builder/SpockRestAssuredWhen.java | 38 + .../cloud/contract/verifier/builder/Then.java | 21 + .../contract/verifier/builder/Visitor.java | 21 + .../builder/WebTestClientAcceptor.java | 28 + ...WebTestClientJUnitMethodBodyBuilder.groovy | 64 - .../builder/WebTestClientRequestGiven.java | 45 + .../builder/WebTestClientResponseWhen.java | 45 + ...ebTestClientRestAssured3StaticImports.java | 52 + .../WebTestClientRestAssuredImports.java | 58 + .../cloud/contract/verifier/builder/When.java | 21 + .../contract/verifier/builder/XmlImports.java | 52 + .../builder/imports/BaseImportProvider.groovy | 2 + .../builder/imports/HttpImportProvider.groovy | 1 + .../builder/imports/ImportDefinitions.groovy | 1 + .../imports/MessagingImportProvider.groovy | 1 + .../verifier/config/TestFramework.groovy | 48 +- .../verifier/file/ContractMetadata.groovy | 139 +- .../verifier/util/ContentUtils.groovy | 19 + .../util/JsonToJsonPathsConverter.groovy | 8 +- .../verifier/util/MapConverter.groovy | 19 + .../verifier/GeneratorScannerSpec.groovy | 3 +- .../verifier/builder/BlockBuilderTests.java | 61 + .../verifier/builder/ClassBuilderSpec.groovy | 16 +- .../builder/ContractHttpDocsSpec.groovy | 112 +- .../builder/GeneratedTestClassTests.java | 138 ++ .../JaxRsClientMethodBuilderSpec.groovy | 751 +++++---- .../MessagingMethodBodyBuilderSpec.groovy | 1416 ++++++++++++----- .../builder/MethodBodyBuilderSpec.groovy | 1053 +++++++----- .../verifier/builder/MethodBuilderSpec.groovy | 12 +- ...vcMethodBodyBuilderWithMatchersSpec.groovy | 237 ++- .../builder/SingleTestGeneratorSpec.groovy | 71 +- .../SpringTestMethodBodyBuildersSpec.groovy | 1349 ++++++++-------- .../builder/XmlMethodBodyBuilderSpec.groovy | 89 +- .../YamlMockMvcMethodBodyBuilderSpec.groovy | 991 +++++------- .../verifier/util/SyntaxChecker.groovy | 89 +- .../src/test/resources/application.properties | 1 + .../name-with-hyphen/car-rental/diff.groovy | 13 +- .../directory/with/scenario/01_login.groovy | 13 +- .../with/scenario/02_showCart.groovy | 13 +- .../directory/with/scenario/03_logout.groovy | 13 +- .../with/stubs/different/diff.groovy | 13 +- .../with/stubs/other/different/diff.groovy | 13 +- .../directory/with/stubs/other/other.groovy | 13 +- .../directory/with/stubs/other/sample.groovy | 13 +- .../with/stubs/package/exceptions/test.groovy | 13 +- .../stubs/package/v1/exceptions/testv1.groovy | 13 +- .../stubs/package/v2/exceptions/testv2.groovy | 13 +- .../src/test/resources/logback.xml | 15 + .../strange_[3.3.3]_directory/02_login.groovy | 13 +- .../bar/03_login.groovy | 14 +- .../foo/01_login.groovy | 13 +- .../worksWithPdf_request_request.pdf | Bin 0 -> 14631 bytes tests/pom.xml | 63 +- 238 files changed, 14295 insertions(+), 6992 deletions(-) create mode 100644 spring-cloud-contract-verifier/_request_request.json create mode 100644 spring-cloud-contract-verifier/_request_request.pdf create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Acceptor.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BaseClassProvider.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyAssertionLineCreator.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodGeneration.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodGeneration.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodVisitor.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyParser.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyReader.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassAnnotation.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassAnnotationsBuilder.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassBodyBuilder.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassMetaData.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassVerifier.java rename spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/{CommunicationType.groovy => CommunicationType.java} (80%) create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ComparisonBuilder.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ContentHelper.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CookieElementProcessor.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CustomImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CustomStaticImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultBaseClassProvider.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultClassMetadata.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultJsonStaticImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultStaticImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitAcceptor.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitJUnitMethodBodyBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRequestGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitResponseWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRestAssuredImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRestAssuredStaticImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Field.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/FieldBuilder.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassDataForMethod.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassDataForMethod.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassMetaData.java rename spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/{ClassVerifier.groovy => GeneratedTestClass.java} (59%) create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedTestClassBuilder.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericBinaryBodyThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericHttpBodyThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericJsonBodyThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericTextBodyThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericXmlBodyThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Given.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyBodyParser.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyClassMetaData.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyComparisonBuilder.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/HttpSpockMethodRequestProcessingBodyBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Imports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ImportsBuilder.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4IgnoreImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4IgnoreMethodAnnotation.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4Imports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4MethodAnnotation.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4OrderClassAnnotation.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4OrderImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5IgnoreImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5IgnoreMethodAnnotation.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5Imports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5MethodAnnotation.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5OrderClassAnnotation.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5OrderImports.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodMetadata.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaClassMetaData.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaJaxRsThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaJaxRsWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingBodyParser.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingWithBodyThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredWhen.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaTestGenerator.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaTestGenerator.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsAcceptor.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsBodyParser.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientJUnitMethodBodyBuilder.groovy delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientSpockMethodRequestProcessingBodyBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestCookiesWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestHeadersWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestInvokerWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestMethodWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsResponseCookiesThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsResponseHeadersThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsStaticImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsStatusCodeThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsUrlPathWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsWhen.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonBodyVerificationBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonBodyVerificationBuilder.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonPathImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingAssertThatThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingAssertThatWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyParser.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingFields.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingHeadersGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingHeadersThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingImports.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingReceiveMessageThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingSpockNoMessageThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingStaticImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingTriggeredByWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingWithBodyThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MetaDataBuilder.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAcceptor.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAnnotationBuilder.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAnnotations.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodMetadata.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodMetadataBuilder.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodVisitor.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcAcceptor.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcAsyncWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcBodyGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcCookiesGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcHeadersGiven.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcJUnitMethodBodyBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMultipartGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcQueryParamsWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRequestGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcResponseWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRestAssuredImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRestAssuredStaticImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcUrlWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/NameProvider.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/OurCallable.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/QueryParamsResolver.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RequestProcessingMethodBodyBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredBodyParser.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredCookiesThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredHeadersThen.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredStatusCodeThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredVerifier.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleMethodBuilder.java rename spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/{SingleTestGenerator.groovy => SingleTestGenerator.java} (61%) create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockIgnoreImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockIgnoreMethodAnnotation.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsBodyParser.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingBodyParser.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingEmptyThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingGiven.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingWithBodyThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodMetadata.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcMultipartGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcRequestGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcResponseWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockOrderClassAnnotation.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockOrderImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredBodyParser.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredThen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Then.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Visitor.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientAcceptor.java delete mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientJUnitMethodBodyBuilder.groovy create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRequestGiven.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientResponseWhen.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRestAssured3StaticImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRestAssuredImports.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/When.java create mode 100644 spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/XmlImports.java create mode 100644 spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilderTests.java create mode 100644 spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedTestClassTests.java create mode 100644 spring-cloud-contract-verifier/src/test/resources/application.properties create mode 100644 spring-cloud-contract-verifier/src/test/resources/logback.xml create mode 100644 spring-cloud-contract-verifier/worksWithPdf_request_request.pdf diff --git a/docs/src/main/asciidoc/verifier_contract.adoc b/docs/src/main/asciidoc/verifier_contract.adoc index 74e419dddd..991bf3b09f 100644 --- a/docs/src/main/asciidoc/verifier_contract.adoc +++ b/docs/src/main/asciidoc/verifier_contract.adoc @@ -1800,7 +1800,7 @@ following code listing shows the `SingleTestGenerator` interface: [source,groovy] ---- -include::{verifier_core_path}/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy[indent=0,lines=17..-1] +include::{verifier_core_path}/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.java[indent=0,lines=17..-1] ---- Again, you must provide a `spring.factories` file, such as the one shown in the following diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Cookies.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Cookies.groovy index 145b90328f..4717fb2e5b 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Cookies.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Cookies.groovy @@ -16,6 +16,8 @@ package org.springframework.cloud.contract.spec.internal +import java.util.function.Consumer + import groovy.transform.EqualsAndHashCode import groovy.transform.ToString import groovy.transform.TypeChecked @@ -48,6 +50,12 @@ class Cookies { } } + void executeForEachCookie(Consumer consumer) { + entries?.each { + cookie -> consumer.accept(cookie) + } + } + DslProperty matching(String value) { return new DslProperty(value) } diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Headers.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Headers.groovy index f7b34f39a4..9931991184 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Headers.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/Headers.groovy @@ -16,6 +16,7 @@ package org.springframework.cloud.contract.spec.internal +import java.util.function.Consumer import java.util.regex.Pattern import groovy.transform.EqualsAndHashCode @@ -23,7 +24,6 @@ import groovy.transform.ToString import groovy.transform.TypeChecked import groovy.transform.stc.ClosureParams import groovy.transform.stc.SimpleType - /** * Represents a set of headers of a request / response or a message * @@ -58,6 +58,12 @@ class Headers { } } + void executeForEachHeader(Consumer
consumer) { + entries?.each { + header -> consumer.accept(header) + } + } + void headers(Set
headers) { entries.addAll(headers) } diff --git a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/RegexProperty.groovy b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/RegexProperty.groovy index caefaaae5d..65d33a2f5c 100644 --- a/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/RegexProperty.groovy +++ b/spring-cloud-contract-spec/src/main/groovy/org/springframework/cloud/contract/spec/internal/RegexProperty.groovy @@ -110,15 +110,24 @@ class RegexProperty extends DslProperty implements CanBeDynamic { } Object generate() { - String generatedValue = new Xeger(this.pattern.pattern()).generate() - switch (this.clazz) { - case Integer: return Integer.parseInt(generatedValue) - case Double: return Double.parseDouble(generatedValue) - case Float: return Float.parseFloat(generatedValue) - case Long: return Long.parseLong(generatedValue) - case Short: return Short.parseShort(generatedValue) - case Boolean: return Boolean.parseBoolean(generatedValue) - default: return generatedValue + int retries = 3; + try { + String generatedValue = new Xeger(this.pattern.pattern()).generate() + switch (this.clazz) { + case Integer: return Integer.parseInt(generatedValue) + case Double: return Double.parseDouble(generatedValue) + case Float: return Float.parseFloat(generatedValue) + case Long: return Long.parseLong(generatedValue) + case Short: return Short.parseShort(generatedValue) + case Boolean: return Boolean.parseBoolean(generatedValue) + default: return generatedValue + } + } catch(NumberFormatException ex) { + if (retries > 0) { + retries = retries - 1 + return generate() + } + throw ex } } diff --git a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverterSpec.groovy b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverterSpec.groovy index 426a904efb..55022fe561 100755 --- a/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverterSpec.groovy +++ b/spring-cloud-contract-tools/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/converter/RecursiveFilesConverterSpec.groovy @@ -101,6 +101,16 @@ class RecursiveFilesConverterSpec extends Specification { def "on failure should break processing and throw meaningful exception"() { given: def sourceFile = tmpFolder.newFile("test.groovy") + sourceFile.text = """\ +org.springframework.cloud.contract.spec.Contract.make { + request { + method GET() + url '/foo' + } + response { + status OK() + } + }""" and: def stubGenerator = Stub(StubGenerator) stubGenerator.canHandleFileName(_) >> { true } diff --git a/spring-cloud-contract-verifier/_request_request.json b/spring-cloud-contract-verifier/_request_request.json new file mode 100644 index 0000000000..26c2b2f565 --- /dev/null +++ b/spring-cloud-contract-verifier/_request_request.json @@ -0,0 +1,3 @@ +{ + "status": "REQUEST" +} diff --git a/spring-cloud-contract-verifier/_request_request.pdf b/spring-cloud-contract-verifier/_request_request.pdf new file mode 100644 index 0000000000000000000000000000000000000000..69503635d87cbdfa660d5cd8be66d3e74b3b20e8 GIT binary patch literal 14631 zcmch;Wn3KHw(c83@Bksf9THp`ZQR}6-Ra=&5Fog_yEhWtEx5Zw1Hs*0FYmkd-e;}7 z&i>u=;hx)FHmYXLn&Us7t}i_wGI?Q9I!1a{M6!d}n3(Y`B4%U(GQS;&6KfFz+1ZF0nSjJP!~i*BATdDX?IJVl+kxy~O_l$SSc!Rg z5lyU(|LTtT|L+eX^FJk`>}G313{Y1zF?~zJ#M;c!oS21!7$6F=bTqMl+glnqnh2X1 z*%-gI`o~`0z~0J%_%8@THkM9S)(*rh!~l7F6JwB(qmBJr>TkIb1JvF~FcLGpt#2G8 ztc^`v-%h-RtpA8jZHO5e--e+`3{bSOaeV9I?_;GmqQs1BfA{D7AKd;s9)N@}u@<)h z6T1nc0W*^+6EhP#yD1Z^5sR_0u>m^^8_*bN$jZq3|K399uOc`&+M5_yA-bj;85*yf z=^N^^BYaCv^ivn*_p3tb(L^=$HAZ&!S9ks>9bPoc|M_G10{pv+aTtcbs`nrF{$Hsh z;$KAmQ*H7FW+o1Qk^LLeKT0NK;AmiJWA;x%V*RH({qh$eo4g|v<9%K4-c`ZCQ2u-Rz<+wWkd3vY ziM68xG21^zEb}G~13{a=B*5_YW#s@8v$HV&rGz&zy*2!=)D%q|Y@Fr3?Q5r3Z+eLMXR^}NaMFXbsY+B+FJ{-a}uxAuU4@cN74 zKf(HIWdDixe+%nBFflPO{B_rV$s{9s9I=bxW8bM)XnKH?#5@aKaFFk^2G!lW7ia+i zFCT`(iG7JG-&pUC9VyNCGsWT!dw2_(qq83oi?aP{LISX@J!(>Zi=<%mt;aSh-nva0 z`jO1>gbyB@9}xa=1!Tr@e`+$Vm?pz_j|{o7tSRC8Z~?TP!XP2~C<71~ zFw5h`h$-Ys{@Uyeb#Dw$cUU9Ru_0neG8k&he@Z@q@rkbLLHr2?SFMxj6-eS{GZ{qr z#7hN~i%aN(#@*N4`8V;h|DWM_`$cmwv%fL@4?2uYjBl^Kf97-Sh2W_yGIv_iJPXkv z`5^cnVNgbp^piO8QCKwpd(vt+=}+HeiX?EWV@^KVp?AUiL9Lj4VB=T*kYtJmO}}12 znH|~aOG}>@nU|f%9vkib3ijZ_3m>~}JAL*(Z6gA`-ll^&Rd#1el!^|V--VzlFsQ_d zwh@rsTy*Jd+I$VYOD=vcj|?F6vbujn3JDZO)9@Il1JIT3D0IJU6Mb&C{KiA3CI}rf^N*j} ze4h4q0P~~PTt`Vi_TI(vrL{Mf1?7)xw{MO*$YlXO;(fNo2=$FNlYA$)d=`knLLENF z1DRm64Axk?GukJ&poN@a3!qegDq@h#ixDRM;Lf_CT7yKi0uOi%uE4Mkeb=|tET3S) zxm}IH;%`%c_pO#bo+L9Hall%HD!E;_PRtibNVylJDClnB|`#fGD;iK4lh6R?0A8!y18;kz`?0l3$zoe z-%f5T+LQFvq1A|`s~YWD@Pfsqy{d!A6@TmD{pzOcZWa#ri_0acoMVAu>)Vd%Jf z0ctcgH2;n{jdoI*_c2t@j`)q*=o25}agNfzFNz$R;9&n+zsbP5orXO&!~I!*SZ=`> z_5Q8})i!bJj;}b0H6)R^y_(@gaa|z%J|Z;e{gCgA@gbQxIy~BJDV#RI`zy5j|ln-|s*R{V?;jo{*U+EpZhY8CXz0 z_g$!Lg(B(#V$}5E6Dl8qj#46a)D`7guMtvhNOdErZo|Sg7OEk9^(#tDrccVfx1Kn+ zM`9duI7$)d9&(;yM)}C!QAz8clux)8Xm7hUc_UQ)D#Y;Dz8R@5?G{Y|nC9Z;Dk-En z%NDggN_pOc(a2J(yyLPSye7rN%$fT}8pZ@<7x~rTQFU@40uDVmLsQL4-~zS-2BHD? zdlwcmeZK2nO<7?#9UAvvKab(l%od~Eto`|-CZNyu-`oA92>v=^xVZB;CwN3R3~X0F z$C{Yae~bW1kfk;}s~x^_trKb1lbBgwK11w#cDp@K;yt=<2o90=yh9%d_*o~u5(hx= z7_w%U3Kfzu%<$yNnaqR9{9!|%)wAHY+>T&okNzV@rFIL36+;SON^pRtzI+n!$wP)*+svnleMDCP0ZIP6YqEq*&Xqe zUE|F2;fBJ|hxxPeV55{E)TxgSdKAfxpMl=iCth0yWw*1uSx&X5jED4Vm~<-*y{RZK zMx7fTA1~W0&ZS4MS(A4`F0UHjXOt>m@$0S%J~L-osow8UG;3w#O(%Hy&J}?|3Q!Is z@r#cj`X>T+U!2FW?$7SsH6z>{r&RU%atV{EymIIKC?zwIE~IBpe6zMSY6GpOA~)KJ zA8!hr4_dJW)VgmPlnKU^B}_85zb_d-M^5#!Y%M)26VFSI2`zn{=gp24geHxqh?FNf zXE!FLgty0wM`hY$#K5XP^;`*CM@sXz3|>Ttj@h(Q_F|%3x#~CFMw%sZLBr9T!or@$ z6;PV-+Td~@V2Y^dBU~~sEsU50EjXan!WeP;c~9rl?agas%->G1F6hz3q^XkbMu)!Q zv~ybF?KluzaAvD?i!D39g!K5eS@MX~EVtsFr%Xqr%(bfqAI2 z0p&T9l?&sW!LC5_(H7~l1F#JNn0rS230P_BR{XO8IPtv}299~)Q>oL-a!rN})yy1^ z9!2|*{rHOO9NAog>(8eKzg|RdK~|u8cK+KCO-;JtTpp+C*5p_E6*`k=gVb+__m7lo zQp`OJS9%f!hQOw}kTwjg_UX-bVmW@5zY@*t-)U3Gwrpn;+QsgySV&Mv7?PA z0tY>jt)PKta-eu%CT10#IK%C<`3;6`M+n6}qDTXDoL%3o8QZ&(Ts|HoT9~yjS0d}6 zyzmw+A5KKt{sn;VN&G3yXU}iQ(dbU7?{DARJT9jS9W<+ZIjHBBnB3!l6ZQEX$E0c# zgR7gtLmux|)L;&D<(aY!961YOoJwd5pXV)_ThT z+2q11(LJ8|&OFrAuZfbS=fh3Cq`5=rN2VSUeb}*3p&2|!YV*P@U|&NDK(pt``0Fa( zFjJD}tYjfbj^#L_`=YGrF8P%Y%47H48SL4^D@ccFcmN-b{IZ8}MM!j=(Cx!*oW&k_ z?&Sd4HK;RhK!_uoCA}jh=xcL%C-)iOdp5tXd9>Gt&BWw>$^(9YkrhDDmZuNtgu38Tzh|XH z&h52CXo-Lf0+|3@eV*J=9lzH$vOv<)wfuAnT4l55rF9WYBxt1Mp(%#-jZ#k{+{A>K zT)hq(U(U--qP8)H*Xa1Pgvuu8*bhG)q91x%ggE&+Rb87Nw#|*s^_R|in6Xx_EAh=g&f^X*@4}`7^9&CA}0Mki(Y1jQ%6dQEs$D3Sz6g?FEMSZ(HdU!r^ zPl+Eg^<~V{K4pH2ncyIy&+!nH?7~2}`CvvW_faZbF85m|dMtY43<(uA6?ut;;&{Hd zM0adx95^nKtXx_%!%=OjFP|dT`P;FKJMaE%enT7zg;(rV!B|A zkaFBgU#`ag2%r0wll!(xG$Kdu&*)4giJ}376lgdm5cY``p7&TM`T*S zjXOyOv+^Wm$!BvHz2c3_e7{;bmcWax2fClUqtq_9{ zyVB=bD?|30_nqeFXJ;UqYI;7$_kYf`>#ovIkv{D3w4*$|^AV7`B-lLF7poN!UL6E4 zc&aLNK$#?kF9ya35+XzJntj`RD~bY?r9~Vukbk|Fy{JF8T-(fNmHBkMRK}O-srlGE zf4RmxZz}bcc&>inn{PRI{OrXTws&dN*YH4*1bv&{yt7pu*O9SgUyWE`2DLRC$4X(t zt>R|58X`h*>pgk7RZdZ#uI}M^d@j?khDP9{e8Yq0=K0&scxSUM$_)S1qxGY8`%S-q=j&xjzhDvuBU`DBkxtb_BR>B#BoI`1*E-4$IkvfcSACQpuN zl$Z0ud}p#k>`P=HQN(d;$7R!4QI~Fy%&Ew7UOk-U?ea-Yc|&;(#KL3vCf_RWm?T|q zO*2UA%o)tFwQ2&b`I71PI?5k*fm5E>QHC*b`egnk8brTpPjg0WE&QbiJqDGt$gQ*y zGudK&?KxQDvtg)4>Y0ag?Li7{GwX$pj~dh7TD|scZt-MyZFr)^{FLSc9z?ofirW1L zVbN$K=}c!i+oXA>HAP4PcU2KvB+7U z2@%^Z@zqF)fQgQRj1%gkRtH6g0jv2jd;B!umwN~cYp!UPM+gm~s{0o(Z`hZI>Z>Rg z;*O}cXaUP(&XpNg0M4%O3)J;tJl)PUW*T%zCRPiC^+|Om24w_DMRAUyb!G$$4o7a7 zzd5UCk6>;{m-}yOk`{((V?`#Xw@fnB&2A7q5=3gS=K^}G=NAsI@G|no_mMFB9Wlp0 zFW?=?++cEbu9}__n-Lm@l+j2T4jwUhB(?Rgn)#Rztq0oT9QHNW5MGga^+rwvIr{PD z$n8@S6h-YZJEvwC@NJYmggnPRkBn98Ep{x}9N|kDIF)5)m?4)@j4^J6J5<>Hrdt`Z z;{E}5K|B`*cln8MX!)$3JG^1@Pb<%9r=r`3(}5{<8^XanSBljXu}kdLfc^{iipyE< zOo~cg+6;>7_Es9Xjln0T)d-he9#=%YL7S?d8cXNXONz(jR!#MSEh1WZkU~fSB(Hp$ zuygP}_@=R5#zWCVbGd>i?|4#oLU&4cdUXoL@K<{g!6fe_@3bsP5484u&7!D|=sxO+ z;zjO-`86PGyW_&=eC>`yxBsw?m`)w(_kI^c$>;{!d9kasC0bNixnY{CAa{t;Hs}w= zaxY5yNJ|g1VS_8??g(KO*6!8i2F!Wx0>w>OQqS-P#yQwkrj>s6lTBzt57c?Rs~A3d zP>;cRg{xdE;Dws^lUPsC#@BSktYEob1v_a^^2o3+8~N;HyjXg{fL^r?n+=Qeh&$CM z9Z!lEl6EY<;OULZvWl_#ku^05%kC0Q<4!Ld~LSNtrIl+d%K~*^rS(?r_iJXhdvJ7U*YflwwKJ z0=?U-Qx^Jt5&6jD#$TP7x<~QP+(j+U66=z*RiZjMwMc?GJ!WWHFKLxv8G1u7Zk1#i z=6py?FRoo_BQnJW!GUzU+)5PJsDI<)3e8*yUayd$|3YxwgF$%*kpHoWd=0H!_(cz$ zITFq$!Fi$>A#4`&6E-^j=cPg`^_H_60#Z&4fYrv^P6DKH?}yk>WN$F*6jt#%jm$=`tJrom&PJ!@eHoh2FjJ=4 zwllYE-LW~=a?);gtaqZ*@Y4QBVoE1`^^KMO}o?ju?q?z=M#O~?Ta2C`^6tIBA<)>Nuw+RKD+%B z*Z*O;%YqOvGchxZe(dmEm>}_oLq1yjW#gW;3My%HFTC1YJ+9u$uLwanch|N|O5PjG z$R*_xbu=ehr7yEen}}Y|?tGUvOUg1!rwp$-N!tjk5mrNs>H$3qApu~*gVAWqE#GNjUkpt@~wXBC5^4PY~ zPxIp38{`)iB?iaC1*Vj`t@h+u=5jYska70L3|uC}XQ8%>XD(KgTOvgN2*gfjW2*Ax z3d0{m@BUg7WVws}2{ErV<4a9-TgK;_d>CCis%72v3>FSHE*ef=-d}2R0K9GS^v!~v znALhJ$)BQBth$Gkzhp`#b?kw)l549DKBEUq45@KhpB1Ck^|MkAXOG+z#aht!MlVEl zUrm&i(ENj^Klms?qNc`q**U>`2>C+}JFa@<+d*{#7S zR-SIU6-jhKk~(9;V?)VV%#2!dTjSGhz9C<~gni%HHUe?ZyMl&t?+7xu%#O}8^2Zk4 zWn`@lTU~@54KsOYOg-ShDb?m?MIYOgh7)yp8iMMW@mtztwBisDtj5^!meGrP$k?nU z^UP9eDeY+Aca?HEs>h}Ub0Ei}?h=FTKKfyMUtqhtAytyn+pHHqrB;$u>)zaI#@dRN z-NQ8T@SQ*U)RtAHvCidJ>WNn~$>ItjAA7H+#cmu=3IzsRq0gZMQPj3y+T7{OwnIX; z4LIRf#NyVqJXWJw8u@s2>CeDRA5;DP8rXje0 za9egMNMl_}8rtD)`0Y1+thzbt$LVo5ObC367D2U9X{qei7vb7GE#zxg$BpTjWO-il zMrng?%TYtKxlM!T<}!7plx9H0VL|I)wQqm;N)ZqIG_~I4D$X)^)w0pPB5tN&p%c9l zIfJh=V%pF_2d1g}1hG@q+_fT20d6F$xF0bGJ+;TeQ&Y1st>9UO{;0rwv8 zT{f36QN1RpV??ilYJBV#PPW|U6l{LFH|ut$f`&Im!yL2pJ;o9D3<|gRPYSH`2UF+< zC{!p_G75{KA7q`p>*3!ACrDjZ7TNMJjT1<@b}@=db0L&t=>?%&zs8vN?gn8;aV>(8 z8G9bCn88Y7xL4Jgu*hJ!BYzZc?D+=t|pK+JbmgsqygCFleh(+u#(66iJf7VVdr|F+_MriJLuUINk zC+>Fd(l?6C5%@v~CNRg*I)&cG$Y6_Gc@cM)-nq-phf*?5iHr?30!#S*2C4`O@Acz2 zgSYev#dZ7>{Etf`*TD0<$t?dJ0Z+?D?w07*EuxOgJYyXwz z%S+^1bN}oG!1;j64v)#>5_JH{mh$nPzYjkr1Hu5@5EM-#>TfUc+0Nrm*iIz%$z7qV z`%hjd?@r$lDcTT2Cx7^G=HkLHL&w+p)y-JjRLncLLmC$B-aK{m*|;VjA789D0Gq<-^pJ(Hb#`UhI4us+ZhPk;N-wJXxE z(e~p7J^?(j_(`@6hF3fgM!v7LF?>rQm{Er}Hb@%#u&}GrGKmIh7m}&jZ&r%=ZO(WC} zve4;6(qFPv0}E0_<>JX+5P1>qdM@w6=?xeSs0`H18+t42t1J!60Ewvikr!{p)8Xf8 zEkAx?z0&IlRMa;m?nqb@)v5f{kaks1(BTwPYI1ub?oCh6?DrgC2$LI$Txgv5firjo zypm=3{@bw_qbHvELuB&)-kh_T{di+rS;SEt*GWS%V6#1 za=e1@dOM|9vmPDa^J>GL9+O7Kos&j1#`!*E=KP0Y-j+@G?w{!X$52Ks{geeERo^>7 z&=wjBqH@ccS`}8gRzK(;4E(VkIdEkEP%5gX(HAoYnr!j2%Fw2xxrb$Tm3+xeG zta;$;nr9))vvA#di|c%3TIwNWiEKQL9!D>! z)o!(AOUD^?HEZ11?D%&ni@5Fyp%wchl}BjVe4yF(c0{SkbOQeVk=Ou_kZWiHb!wQOJrL8Bl(RSmb8jd@~2ZFHreNHPMVl~8B$Q;09^!W1EmbEMQjM8 zv7p?8iJ+Vy`8MCPU8J;x0awrthw0GmkEb3>is)0Fx=P9+EgrG?2Cj<{te;y?9Fe3F z$FerMxy-|d;v-WHs2OfCJ1Ny}=7w|5sVNz8EncR9%ohC<;W>*TH)X9EM&#Fc3xe}> z5zP-W%>(*zTl&xW6^zh;DQ8txFz4Z}+Xhl^T+Oo^U+G^y07yr;;hTZ@ZbY@#4Z~KHTS_mAEX#GPZ1VzaHpkPsWxksr-k9%M31 z30iSWWpma>5u+Ypw3+p=(~0f(=R*DBScATE6O}VU?oYv?$H$#OZuaooNHGtqx$*hL z{7HZ)pL$sL;Dcj5w`hhilL*>ZkvO-kNdFAX{zh!X}+mi=7_wQGi#%q_s$BqRy`c`F(`sJ-!-K@O1_3&cu7f_ zH{GaRY0Bor^QW+c44EUh45>*l@BeHJft^xOmfS8|N;+(rbt$r8<`ML$W%JslO6H7% z&hl?3q9uBaQ~+Ex2F*<(IGe3A$3xN0MtlCCHg5w;G3e!-;?o8fQ7;gia}yXpx*>|X zOwH4VLb4;eC{Z6<+to-ggldX|=caY%vLgPRC#JNYxBJhaaaME}ADY7*_Z21TX3J>= zZ-?8|oPKo5&1Av6Toegf@Gk%JG!=+8HF>7!f*YR5^I5t5`KNV}i-arn9& zwHW$32UK~(c=d$$m;mTA3%O~=KE{)jSM6*91=e5?vN|kF?VHJ1RLN{S&m@YM&A@vV?Vgk+vaE-rm?*F86$Q zHk$c~*#+j$bq1Q5s<5T1<_(*d;m(qdm_Y%k-m(p4b=<~_hKr_d8ZW$~H)i z?fv(g$TOAI23FmXfjaF<=)SBy2EJ;=29>LkQ~twMOK$gv{ZTd~8zN3a>G#mX@zdoc$JiL^-Mb)W1Du z@)gPmqPG$UYS~liwq#{aVOHYp<7CR9D`QpS+Hw0@iRca(>>uf+qBg7|1n2rLVL5&o z-6fj7UFfIT2bA%nPnFLkLHPBi^A<25bOm#SbMQBqE+M$9na8B`gh@VGDNZJ-1<-Ux zHMQ4s(@$T(`Q4#lo_hhUjH? z;$*vSYoJe8(M28IJl3kLp~97mXJ+ms%gP1*Y;cr0b;Mcu4S|58i%_7Bn1e0f^XHl; zDBOyP8>O{C1kVUF-y$qWkqS2-q)l}%P$KDs_b(g zu1~xWl5GFS%BF)9KkCyR8Pj zU*t@bRG>023(6n@k{suPmp{;ixobOF@wd;7ceB;JO0MFMwU*lY$E*=_oJn6iW zlalzzVM@;%3#-#rK|ulWK%|Mxgy`6K(opr9YcJu+m1o}d_{Wkw;;7pK8A2l2V~$su z7))2G#prwKWC^nHTwE4U<9daZ+n@jVPX`7_e0iu3iwb6|l5i~dk(Vmr%cZM1@~SrI z`GTAyCn*IqnnM_h&E-KyEJ&)0+M}pl=*&hIIE6hYM%w)i1(o;?Vp=l>Mls3ZUSJT! z#fH*Q&kJJWaa1(-Hg_w=PQ^-KvJhBUjMtdLs2P)#(q9ZV@HZ=<>ZpuwKi0>N4&L2K zx^GI-I@c_Z2d5LTwq4FnmXgk& zSISnUViMxvW5<*&Czm@oVa*j-RkM^Rg&P%C0XI9ce%$*{1fPm|Mum)P^4FM-YEJNm zZ%m803d7NV{?dHmYcRu>v2?vT7=o~+PqX-=VR6r@1=snMYo*dx-N@ojGRmwLsH)j^(>~ilo{M!55#f`KcSRxLsqUaTd3T zsjg`mU6!~idGR~-xCX&h>kDA&7hU5Es2M^e{WITqNLA?|oSnz=tu$})gQH`LC;ats z2~A-XKu>Z*^fED>!Tx`Le*YzZH+58%By*qG|z!5J}Dc}=zQ|$zB{-$ ztyQA1Hf1rt@hptba#O!c3$ux_?c-+Q3137w9C4_my?+ zd~uDqMp7lWK~1VM3W|ku1%ht1>eoq$Lwl5r9`~&5%C7;1s!1G5i>9tMgGde}RAS8E z)1D5P+O$l^dJ48^R7yZ95NgA)1ShO0gx4`UwlR_VgyQqmzTzL5_l0%N)2}EP)6F=y z-dPxwkO1)9o?ZZEQd6K}A-080k2p?dfVq~r`!aS82(Ub>i8Gl)L&Q09-!cQnph>Z> z8xJ?9RpE(9VTrO2 zR?eh1M@y5{{NdhVMl+jbe=%-b5o)E=+vzmaV2$BISce-BQA%&ccGI#V#e?S(w;Wzw z=xJP=Sd39MeGTp~sKcMn(M%&9ozTs0RjF_u%-a~gh80YfUd6$}odJqFHl#jbC) zj)>Z{d*wrha=e!n0RyE%nq{dYE&J`8NHUtuGMcZGlBL#wNPHRt}Nc)eJh5?ZtZZM5EN>DgDh zgpXK29Dt8ecM{f9yQ*%ZZdsg2|0wy8WZHupRjUy{ZKnJlL+}_1xj{=)ZX)C5MS{8?!^ggBW ziT!(m@jIhZFe4J@XvVSS3Ks^ooZCn%<9zsI*!^(FazTIks3>R%6YGG6VNc3^O!cVOpdjQiG>9F1jCT zYPaktcIPE0aVR-+_tHph!Kj;{`Fj7IHO=gc521A|t$$gJ8FfPc_MJ$?CF9X|LI|1Z z4)Dq52yD;Ho66)ljQ!At!`j=g&U%ZaHs;eGXO=eIihx_gc#?op2QDa|%g#;cNE1!G zq)|%g=o~3Unk6U;Os(;a+xm9qBQ8(CCdn z12mSmwvkwCTh(f72SBTdJnSUTUk8-PztpvfXGZuJ6CwAw6>l!W73jLI?ZI7<-;Z%b z^rghM&1SKm1V#Nu&2Rs4#QNi56Cx}ashfZDZF?dqP%hyiA6(P69qCd$a(g<4FlbT& z(U`@?>Z96YswuApg$_;h;c)(LHA_fgb8X^_h^rN>Yn(xp?ycEhiB=$6E8F7v(_!k8 z8k_X$E{2;)m_V|nSx{1ARv-F#lQ(9G@}93WM-l?{QDgTt7}G~fv((iRpUX_4$)N)B zXNG9rAvFEru6l|I6?~;&g0XFa;T%<3rVIc$=O1V|M?ItdoZ8ZVn5o{7)YzQsPt4WJ z`t9#=+x3-4Wt^6NuBZ_)jN95Pbo#hVeUBDfMfJcgaX^3?bKjbaGiQ}m4Pe`>6Hvf& zJ%X6jrtZQ&bRuXZp%I`20Mk|_HLnmt6pVjWa&hmi-!$S|LzIjGvy=7WfV9$AT|^o-_E3pI zVy3mnOzQq>;+|uXql8ebQh(TM8>GAO^Hfp?C3tywIK$Scq#J=OutjG|qxq6ky0Ay1 zRlI*?MSaVVLo}pRy=mU4FJgISmp_U_wr%Q|mZ5cDTb?SS+)@1X&|#RtBs^Hcjk{t> zkmDMWVh*x-LX|X#oK(UtSkAa2kt2w&aKSsZSB@WKJ*dd< z+oh})887KvN?M@V8OC|l-7=yNfET3Lkm*GiE|Qt0Smb$|OTw(1#qMGaW*X5ra#qC< zpmpl%Nw3Q5j~p7o;j;7NwX5}>T~Jv3QfPXZVpM2s7B!w3{RI~tH(u#y!I_69eHcD= zTz47IcMRO)-(xg1WtB--bc*iAXHtBl8u<8S zjct`(`|*=$;N2Xp7=j!npqMq!)m1HnsC%hoVD^`=jgKaQ@S@Era;lDBMCCt+|V z1S5v^d8^9`Kc!2e1_q{>ECh^_JEkn#p!;=9Vnk$^{5(K9?oGJi2$pQYQO`TJh9kJHrx!vfdj>F?hZtB8^cR$J`QPf|Wk#0*`wUY1fgc7itL7hB}Ayr0kT7hJM=ZTVk+Kf?vVVz_Z{3r$Ud!C*zHC!|wK8c;h$y1QyX zo8-fLtxuu``BWwjl|mH6W(g#}Z{yQyyS8l?uS=Zk*jCu9U<+Q;s-{D^$$CL#g!evN z(lmDC^~2mT)HJW%C@N!yGn}uDVYCG)-pW&r9}`OE^;;fxdofEarbsbEyFCeq*1)Ad zI=sNmv_mv8t+nXphjqtGNK3r>QT1vbxr^$~PK;+sawSz6bdDTa;e~x)s&b>SDf)tk z&+$KkTHHlw8Gd~g85stC&#!R3kV-~$;)yf*^bBBVO7i`;srwxNXH)lynONBVWv0GP zw2VbJ!^gnW7Yt74Aj5f`oFM%@CPa=Sf0IY3$a3SrUSOodKt~pzB;1#UGvc;b-N|~7 zld=&0HGd@@QS69WD69t90ETsAS`OO@(O$d+z0s*JsXfp2!s%RGoKr0CuD+TiVFMR* zYVpo|CmOODvAKSqlpcS%ExqMq&x_~`{*-MeouQlWlfe9*uG*_eX|=~Hi^T^cD@|-Y z0M!X^n}uGN`s0+WIBudKzk>`3yyi2&2Mjh)USoP258j)0ZjAb%#Xm*NS9Uc4q9Gi#Nk;c`SxfKm_tex-&XAe%z5Lj+`yI@xmX)28 zD-U@lJl5C>VKuQWQ(s2)8wf#rV3)#GB46tx`GtBGtKb0f@G;(GzJ>sRjusRop&pq& z9m|Cuwdj^XQq&+Y%Ey}EJ>6c_dG|!|r4M8ovSUl=XXSkCf{J!EkyIb`y+*q296it7Nm-$@FPnO4-cRn4xY0MsVe(P%&nyP8z!?5=TC|FR)PEM6R@B< zbP#TWmQ0XLF&A$dqM`N-pY1AX-*X8Pg2ME3$Zayl(JYf;{n6^G^XnOKRWraOF%@5e zj~Nmz%oyPA7m^-6luj0ETNuZE0t8y?L@4bhiEs3`fsSS)oqx|%sMo1j870E4%pr-h z6gq^^s@ds?gm*u~{`fThW^?&(F0a2#YyT>jfAP*S{;i1rFTHbrTjH4BJaqq;TyO8* rlZzsu!M=O<^iJ{LU0wgpeD~&qGO%}awKp+EWMTv&l97qXi6Z_#FstrE literal 0 HcmV?d00001 diff --git a/spring-cloud-contract-verifier/pom.xml b/spring-cloud-contract-verifier/pom.xml index 5fed3ce4f3..1da11ad111 100644 --- a/spring-cloud-contract-verifier/pom.xml +++ b/spring-cloud-contract-verifier/pom.xml @@ -210,6 +210,25 @@ org.codehaus.gmavenplus gmavenplus-plugin + + + + + addSources + addTestSources + generateStubs + compile + generateTestStubs + compileTests + removeStubs + removeTestStubs + + + + + + org.apache.maven.plugins + maven-compiler-plugin org.apache.maven.plugins diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy index 4ee73f57e7..2c5ba80eea 100755 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/TestGenerator.groovy @@ -42,7 +42,6 @@ import static org.springframework.cloud.contract.verifier.util.NamesUtil.beforeL import static org.springframework.cloud.contract.verifier.util.NamesUtil.convertIllegalPackageChars import static org.springframework.cloud.contract.verifier.util.NamesUtil.directoryToPackage import static org.springframework.cloud.contract.verifier.util.NamesUtil.toLastDot - /** * @author Jakub Kubrynski, codearte.io */ diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Acceptor.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Acceptor.java new file mode 100644 index 0000000000..87581510f6 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Acceptor.java @@ -0,0 +1,23 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface Acceptor { + + boolean accept(); + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BaseClassProvider.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BaseClassProvider.java new file mode 100644 index 0000000000..93efcb86bc --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BaseClassProvider.java @@ -0,0 +1,80 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.io.File; +import java.util.Map; +import java.util.Optional; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties; +import org.springframework.cloud.contract.verifier.util.NamesUtil; +import org.springframework.util.StringUtils; + +class BaseClassProvider { + + private static final Log log = LogFactory.getLog(BaseClassProvider.class); + + private static final String SEPARATOR = "_REPLACEME_"; + + String retrieveBaseClass(ContractVerifierConfigProperties properties, + String includedDirectoryRelativePath) { + String contractPathAsPackage = includedDirectoryRelativePath + .replace(File.separator, "."); + String contractPackage = includedDirectoryRelativePath.replace(File.separator, + SEPARATOR); + // package mapping takes super precedence + if (properties.getBaseClassMappings() != null + && !properties.getBaseClassMappings().isEmpty()) { + Optional> mapping = properties + .getBaseClassMappings().entrySet().stream().filter(entry -> { + String pattern = entry.getKey(); + return contractPathAsPackage.matches(pattern); + }).findFirst(); + if (log.isDebugEnabled()) { + log.debug("Matching pattern for contract package [" + + contractPathAsPackage + "] with setup " + + properties.getBaseClassMappings() + " is [" + mapping + "]"); + } + if (mapping.isPresent()) { + return mapping.get().getValue(); + } + } + if (StringUtils.isEmpty(properties.getPackageWithBaseClasses())) { + return properties.getBaseClassForTests(); + } + String generatedClassName = generateDefaultBaseClassName(contractPackage, + properties); + return generatedClassName + "Base"; + } + + private String generateDefaultBaseClassName(String classPackage, + ContractVerifierConfigProperties properties) { + String[] splitPackage = NamesUtil.convertIllegalPackageChars(classPackage) + .split(SEPARATOR); + if (splitPackage.length > 1) { + String last = NamesUtil.capitalize(splitPackage[splitPackage.length - 1]); + String butLast = NamesUtil.capitalize(splitPackage[splitPackage.length - 2]); + return properties.getPackageWithBaseClasses() + "." + butLast + last; + } + return properties.getPackageWithBaseClasses() + "." + + NamesUtil.capitalize(splitPackage[0]); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilder.groovy index 6b9d9695b0..f253dff74b 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilder.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilder.groovy @@ -16,7 +16,7 @@ package org.springframework.cloud.contract.verifier.builder -import groovy.transform.CompileDynamic + import groovy.transform.CompileStatic import groovy.transform.PackageScope @@ -33,6 +33,8 @@ class BlockBuilder { private final StringBuilder builder private final String spacer private int indents + private String lineEnding = "" + private String labelPrefix = "" /** * @param spacer - char used for spacing @@ -42,6 +44,34 @@ class BlockBuilder { builder = new StringBuilder() } + /** + * Setup line ending + */ + BlockBuilder setupLineEnding(String lineEnding) { + this.lineEnding = lineEnding + return this + } + + /** + * Setup label prefix + */ + BlockBuilder setupLabelPrefix(String labelPrefix) { + this.labelPrefix = labelPrefix + return this + } + + + String getLineEnding() { + return this.lineEnding + } + + /** + * Adds indents to start a new block + */ + BlockBuilder appendWithLabelPrefix(String label) { + return append(this.labelPrefix).append(label) + } + /** * Adds indents to start a new block */ @@ -75,8 +105,27 @@ class BlockBuilder { } BlockBuilder addLine(String line) { + return addIndented(line).append("\n") + } + + BlockBuilder addIndented(String line) { + return addIndentation().append(line) + } + + BlockBuilder addIndented(Runnable runnable) { addIndentation() - builder << "$line\n" + runnable.run() + return this + } + + BlockBuilder addLineWithEnding(String line) { + addIndentation() + append(line).addEndingIfNotPresent().addEmptyLine() + return this + } + + BlockBuilder addEndingIfNotPresent() { + addAtTheEnd(lineEnding) return this } @@ -85,22 +134,49 @@ class BlockBuilder { return this } - @CompileDynamic - private void addIndentation() { + BlockBuilder appendWithSpace(String text) { + return addAtTheEnd(" ").append(text) + } + + BlockBuilder appendWithSpace(Runnable runnable) { + addAtTheEnd(" ") + runnable.run() + return this + } + + // synactic sugar + BlockBuilder append(Runnable runnable) { + runnable.run() + return this + } + + BlockBuilder append(String string) { + builder << string + return this + } + + BlockBuilder addIndentation() { indents.times { builder << spacer } + return this } @PackageScope - BlockBuilder addBlock(MethodBuilder methodBuilder) { + BlockBuilder inBraces(Runnable runnable) { + builder.append("{\n") startBlock() - methodBuilder.appendTo(this) + runnable.run() endBlock() - addEmptyLine() + addAtTheEnd('\n') + addLine("}") return this } + boolean endsWith(String text) { + return builder.toString().endsWith(text) + } + /** * Adds the given text at the end of the line * @@ -110,10 +186,23 @@ class BlockBuilder { String lastChar = builder.charAt(builder.length() - 1) as String String secondLastChar = builder.length() >= 2 ? builder. charAt(builder.length() - 2) as String : "" - if (endsWithNewLine(lastChar) && aSpecialSign(secondLastChar, toAdd)) { + boolean isEndWithNewLine = endsWithNewLine(lastChar) + boolean lastCharSpecial = aSpecialSign(lastChar, toAdd) + boolean secondLastCharSpecial = aSpecialSign(secondLastChar, toAdd) + boolean lineEndingToAdd = toAdd == lineEnding + // lastChar = [;] , toAdd = [;] + if (lastChar == toAdd) { return this } - else if (endsWithNewLine(lastChar) && !aSpecialSign(secondLastChar, toAdd)) { + // secondLastChar = [ ], lastChar = [{] , toAdd = [;] + else if ((!isEndWithNewLine && lastCharSpecial) && lineEndingToAdd) { + return this + } + // secondLastChar = [{], lastChar = [\n] , toAdd = [;] + else if (isEndWithNewLine && secondLastCharSpecial) { + return this + } + else if (isEndWithNewLine && !secondLastCharSpecial) { builder.replace(builder.length() - 1, builder.length(), toAdd) builder << '\n' } @@ -131,7 +220,12 @@ class BlockBuilder { if (!character) { return false } - return character == "{" || character == toAdd + return character == "{" || + (character == spacer && toAdd == spacer) || + (character == spacer && toAdd == " ") || + character == toAdd || + (endsWithNewLine(character) && + (toAdd == '\n' || toAdd == " " || toAdd == lineEnding)) } /** diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyAssertionLineCreator.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyAssertionLineCreator.java new file mode 100644 index 0000000000..21f070ad7d --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyAssertionLineCreator.java @@ -0,0 +1,130 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.regex.Pattern; + +import org.springframework.cloud.contract.spec.internal.DslProperty; +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.spec.internal.FromFileProperty; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class BodyAssertionLineCreator { + + private final BlockBuilder blockBuilder; + + private final BodyReader bodyReader; + + private final String byteArrayString; + + private final ComparisonBuilder comparisonBuilder; + + BodyAssertionLineCreator(BlockBuilder blockBuilder, GeneratedClassMetaData metaData, + String byteArrayString, ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.bodyReader = new BodyReader(metaData); + this.byteArrayString = byteArrayString; + this.comparisonBuilder = comparisonBuilder; + } + + void appendBodyAssertionLine(SingleContractMetadata metadata, String property, + Object value) { + if (value instanceof String && ((String) value).startsWith("$")) { + String newValue = stripFirstChar((String) value).replaceAll("\\$value", + "responseBody" + property); + this.blockBuilder.addLineWithEnding(newValue); + } + else { + this.blockBuilder.addLineWithEnding( + getResponseBodyPropertyComparisonString(metadata, property, value)); + } + } + + /** + * Builds the code that for the given {@code property} will compare it to the given + * Object {@code value} + */ + private String getResponseBodyPropertyComparisonString( + SingleContractMetadata singleContractMetadata, String property, + Object value) { + if (value instanceof FromFileProperty) { + return getResponseBodyPropertyComparisonString(singleContractMetadata, + property, (FromFileProperty) value); + } + else if (value instanceof Pattern) { + return getResponseBodyPropertyComparisonString(property, (Pattern) value); + } + else if (value instanceof ExecutionProperty) { + return getResponseBodyPropertyComparisonString(property, + (ExecutionProperty) value); + } + else if (value instanceof DslProperty) { + return getResponseBodyPropertyComparisonString(singleContractMetadata, + property, ((DslProperty) value).getServerValue()); + } + return getResponseBodyPropertyComparisonString(property, value.toString()); + } + + /** + * Builds the code that for the given {@code property} will compare it to the given + * byte[] {@code value} + */ + private String getResponseBodyPropertyComparisonString( + SingleContractMetadata singleContractMetadata, String property, + FromFileProperty value) { + if (value.isByte()) { + return this.comparisonBuilder.assertThat(this.byteArrayString) + + this.comparisonBuilder.isEqualToUnquoted(this.bodyReader + .readBytesFromFileString(singleContractMetadata, value, + CommunicationType.RESPONSE)); + } + return getResponseBodyPropertyComparisonString(property, value.asString()); + } + + /** + * Builds the code that for the given {@code property} will compare it to the given + * String {@code value} + */ + private String getResponseBodyPropertyComparisonString(String property, + String value) { + return this.comparisonBuilder.assertThatUnescaped("responseBody" + property, + value); + } + + /** + * Builds the code that for the given {@code property} will match it to the given + * regular expression {@code value} + */ + private String getResponseBodyPropertyComparisonString(String property, + Pattern value) { + return this.comparisonBuilder.assertThat("responseBody" + property, value); + } + + /** + * Builds the code that for the given {@code property} will match it to the given + * {@link ExecutionProperty} value + */ + private String getResponseBodyPropertyComparisonString(String property, + ExecutionProperty value) { + return value.insertValue("responseBody" + property); + } + + private String stripFirstChar(String s) { + return s.substring(1); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodGeneration.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodGeneration.groovy deleted file mode 100644 index 4095747ca1..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodGeneration.groovy +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - - -import org.apache.commons.text.StringEscapeUtils - -import org.springframework.cloud.contract.spec.internal.BodyMatcher -import org.springframework.cloud.contract.spec.internal.MatchingType -import org.springframework.util.SerializationUtils - -/** - * @author Marcin Grzejszczak - * @author Olga Maciaszek-Sharma - * @since 2.1.0 - */ -trait BodyMethodGeneration { - - // Doing a clone doesn't work for nested lists... - Object cloneBody(Object object) { - if (object instanceof List || object instanceof Map) { - byte[] serializedObject = SerializationUtils.serialize(object) - return SerializationUtils.deserialize(serializedObject) - } - try { - return object.clone() - } - catch (CloneNotSupportedException ignored) { - return object - } - } - - void addColonIfRequired(Optional lineSuffix, BlockBuilder blockBuilder) { - lineSuffix.ifPresent({ - blockBuilder.addAtTheEnd(lineSuffix.get()) - }) - } - - void addBodyMatchingBlock(List matchers, BlockBuilder blockBuilder, - Object responseBody, boolean shouldCommentOutBDDBlocks) { - blockBuilder.endBlock() - blockBuilder.addLine(getAssertionJoiner(shouldCommentOutBDDBlocks)) - blockBuilder.startBlock() - matchers.each { - if (it.matchingType() == MatchingType.NULL) { - methodForNullCheck(it, blockBuilder) - } - else if (MatchingType.regexRelated(it.matchingType()) - || it - .matchingType() - == MatchingType.EQUALITY) { - methodForEqualityCheck(it, blockBuilder, responseBody) - } - else if (it.matchingType() == MatchingType.COMMAND) { - methodForCommandExecution(it, blockBuilder, responseBody) - } - else { - methodForTypeCheck(it, blockBuilder, responseBody) - } - } - } - - String quotedAndEscaped(String string) { - return '"' + StringEscapeUtils.escapeJava(string) + '"' - } - - abstract void methodForNullCheck(BodyMatcher bodyMatcher, BlockBuilder bb) - - abstract void methodForEqualityCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object body) - - abstract void methodForCommandExecution(BodyMatcher bodyMatcher, BlockBuilder bb, Object body) - - abstract void methodForTypeCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object body) - - String getAssertionJoiner(boolean shouldCommentOutBDDBlocks) { - return shouldCommentOutBDDBlocks ? '// and:' : 'and:' - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodGeneration.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodGeneration.java new file mode 100644 index 0000000000..408f1a1889 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodGeneration.java @@ -0,0 +1,84 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.List; +import java.util.Optional; + +import org.apache.commons.text.StringEscapeUtils; + +import org.springframework.cloud.contract.spec.internal.BodyMatcher; +import org.springframework.cloud.contract.spec.internal.MatchingType; +import org.springframework.util.SerializationUtils; + +/** + * @author Marcin Grzejszczak + * @author Olga Maciaszek-Sharma + * @since 2.1.0 + */ +interface BodyMethodGeneration { + + default Object cloneBody(Object object) { + byte[] serializedObject = SerializationUtils.serialize(object); + return SerializationUtils.deserialize(serializedObject); + } + + default void addColonIfRequired(Optional lineSuffix, + BlockBuilder blockBuilder) { + lineSuffix.ifPresent(s -> blockBuilder.addAtTheEnd(lineSuffix.get())); + } + + default void addBodyMatchingBlock(List matchers, + BlockBuilder blockBuilder, Object responseBody, + boolean shouldCommentOutBDDBlocks) { + blockBuilder.endBlock(); + blockBuilder.addLine(getAssertionJoiner(shouldCommentOutBDDBlocks)); + blockBuilder.startBlock(); + matchers.forEach(it -> { + if (it.matchingType() == MatchingType.NULL) { + methodForNullCheck(it, blockBuilder); + } + else if (MatchingType.regexRelated(it.matchingType()) + || it.matchingType() == MatchingType.EQUALITY) { + methodForEqualityCheck(it, blockBuilder, responseBody); + } + else if (it.matchingType() == MatchingType.COMMAND) { + methodForCommandExecution(it, blockBuilder, responseBody); + } + else { + methodForTypeCheck(it, blockBuilder, responseBody); + } + }); + } + + default String quotedAndEscaped(String string) { + return '"' + StringEscapeUtils.escapeJava(string) + '"'; + } + + void methodForNullCheck(BodyMatcher bodyMatcher, BlockBuilder bb); + + void methodForEqualityCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object body); + + void methodForCommandExecution(BodyMatcher bodyMatcher, BlockBuilder bb, Object body); + + void methodForTypeCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object body); + + default String getAssertionJoiner(boolean shouldCommentOutBDDBlocks) { + return shouldCommentOutBDDBlocks ? "// and:" : "and:"; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodVisitor.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodVisitor.java new file mode 100644 index 0000000000..cb0b8a4e0e --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyMethodVisitor.java @@ -0,0 +1,142 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Iterator; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +/** + * Adds a label, proper indents and line endings for the body of a method. + */ +interface BodyMethodVisitor { + + /** + * Adds a starting body method block. E.g. //given: together with all indents + * @param blockBuilder + * @param label + * @return + */ + default BlockBuilder startBodyBlock(BlockBuilder blockBuilder, String label) { + return blockBuilder.addIndentation().appendWithLabelPrefix(label).addEmptyLine() + .startBlock(); + } + + /** + * Picks matching elements, visits them and applies indents. + * @param blockBuilder + * @param methodVisitors + * @param singleContractMetadata + */ + default void indentedBodyBlock(BlockBuilder blockBuilder, + List methodVisitors, + SingleContractMetadata singleContractMetadata) { + List visitors = filterVisitors(methodVisitors, + singleContractMetadata); + if (visitors.isEmpty()) { + blockBuilder.addEndingIfNotPresent().addEmptyLine(); + blockBuilder.endBlock(); + return; + } + blockBuilder.addEmptyLine().indent(); + applyVisitors(blockBuilder, singleContractMetadata, visitors); + endIndentedBodyBlock(blockBuilder); + } + + /** + * Picks matching visitors. + * @param methodVisitors + * @param singleContractMetadata + * @return + */ + default List filterVisitors( + List methodVisitors, + SingleContractMetadata singleContractMetadata) { + return methodVisitors.stream() + .filter(given -> given.accept(singleContractMetadata)) + .collect(Collectors.toList()); + } + + /** + * Picks matching elements, visits them. Doesn't apply indents. Useful for the // + * then: block where there is no method chaining. + * @param blockBuilder + * @param methodVisitors + * @param singleContractMetadata + */ + default void bodyBlock(BlockBuilder blockBuilder, + List methodVisitors, + SingleContractMetadata singleContractMetadata) { + List visitors = filterVisitors(methodVisitors, + singleContractMetadata); + if (visitors.isEmpty()) { + blockBuilder.addEndingIfNotPresent().addEmptyLine(); + return; + } + applyVisitorsWithEnding(blockBuilder, singleContractMetadata, visitors); + endBodyBlock(blockBuilder); + } + + /** + * Executes logic for all the matching visitors. + * @param blockBuilder + * @param singleContractMetadata + * @param visitors + */ + default void applyVisitors(BlockBuilder blockBuilder, + SingleContractMetadata singleContractMetadata, List visitors) { + Iterator iterator = visitors.iterator(); + while (iterator.hasNext()) { + MethodVisitor visitor = iterator.next(); + visitor.apply(singleContractMetadata); + if (iterator.hasNext()) { + blockBuilder.addEmptyLine(); + } + } + blockBuilder.addEndingIfNotPresent(); + } + + /** + * Executes logic for all the matching visitors. + * @param blockBuilder + * @param singleContractMetadata + * @param visitors + */ + default void applyVisitorsWithEnding(BlockBuilder blockBuilder, + SingleContractMetadata singleContractMetadata, List visitors) { + Iterator iterator = visitors.iterator(); + while (iterator.hasNext()) { + MethodVisitor visitor = iterator.next(); + visitor.apply(singleContractMetadata); + blockBuilder.addEndingIfNotPresent(); + if (iterator.hasNext()) { + blockBuilder.addEmptyLine(); + } + } + } + + default void endIndentedBodyBlock(BlockBuilder blockBuilder) { + blockBuilder.addEndingIfNotPresent().unindent().endBlock(); + } + + default void endBodyBlock(BlockBuilder blockBuilder) { + blockBuilder.addEndingIfNotPresent().endBlock(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyParser.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyParser.java new file mode 100644 index 0000000000..1c3773f7b3 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyParser.java @@ -0,0 +1,164 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +import groovy.json.JsonOutput; +import groovy.lang.Closure; +import groovy.lang.GString; +import org.apache.commons.text.StringEscapeUtils; + +import org.springframework.cloud.contract.spec.internal.DslProperty; +import org.springframework.cloud.contract.spec.internal.FromFileProperty; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.ContentType; +import org.springframework.cloud.contract.verifier.util.ContentUtils; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +import static org.apache.commons.text.StringEscapeUtils.escapeJava; +import static org.springframework.cloud.contract.verifier.util.ContentType.DEFINED; +import static org.springframework.cloud.contract.verifier.util.ContentType.FORM; +import static org.springframework.cloud.contract.verifier.util.ContentType.JSON; +import static org.springframework.cloud.contract.verifier.util.ContentType.TEXT; +import static org.springframework.cloud.contract.verifier.util.ContentUtils.extractValue; + +interface BodyParser extends BodyThen { + + String byteArrayString(); + + default String convertUnicodeEscapesIfRequired(String json) { + String unescapedJson = StringEscapeUtils.unescapeEcmaScript(json); + return escapeJava(unescapedJson); + } + + default String convertToJsonString(Object bodyValue) { + String json = JsonOutput.toJson(bodyValue); + json = convertUnicodeEscapesIfRequired(json); + return trimRepeatedQuotes(json); + } + + default String trimRepeatedQuotes(String toTrim) { + if (toTrim.startsWith("\"")) { + return toTrim.replaceAll("\"", ""); + // #261 + } + else if (toTrim.startsWith("\\\"") && toTrim.endsWith("\\\"")) { + return toTrim.substring(2, toTrim.length() - 2); + } + return toTrim; + } + + default Object convertResponseBody(SingleContractMetadata metadata) { + ContentType contentType = metadata.getOutputTestContentType(); + DslProperty body = responseBody(metadata); + Object responseBody = extractServerValueFromBody(contentType, + body.getServerValue()); + if (responseBody instanceof FromFileProperty) { + responseBody = ((FromFileProperty) responseBody).asString(); + } + else if (responseBody instanceof GString) { + responseBody = extractValue((GString) responseBody, contentType, + o -> o instanceof DslProperty ? ((DslProperty) o).getServerValue() + : o); + } + else if (responseBody instanceof DslProperty) { + responseBody = MapConverter.getTestSideValues(responseBody); + } + return responseBody; + } + + String responseAsString(); + + @SuppressWarnings("unchecked") + default String requestBodyAsString(SingleContractMetadata metadata) { + ContentType contentType = metadata.getInputTestContentType(); + DslProperty body = requestBody(metadata); + Object bodyValue = extractServerValueFromBody(contentType, body.getServerValue()); + if (contentType == ContentType.FORM) { + if (bodyValue instanceof Map) { + // [a:3, b:4] == "a=3&b=4" + return ((Map) bodyValue).entrySet().stream().map(o -> { + Map.Entry entry = (Map.Entry) o; + return convertUnicodeEscapesIfRequired(entry.getKey().toString() + "=" + + MapConverter.getTestSideValuesForText(entry.getValue())); + }).collect(Collectors.joining("&")).toString(); + } + else if (bodyValue instanceof List) { + // ["a=3", "b=4"] == "a=3&b=4" + return ((List) bodyValue).stream() + .map(o -> convertUnicodeEscapesIfRequired( + MapConverter.getTestSideValuesForText(o).toString())) + .collect(Collectors.joining("&")).toString(); + } + } + else { + return convertToJsonString(bodyValue); + } + return ""; + } + + /** + * Converts the passed body into ints server side representation. All + * {@link DslProperty} will return their server side values + */ + default Object extractServerValueFromBody(ContentType contentType, Object bodyValue) { + if (bodyValue instanceof GString) { + return extractValue((GString) bodyValue, contentType, + ContentUtils.GET_TEST_SIDE); + } + if (TEXT != contentType && FORM != contentType && DEFINED != contentType) { + boolean dontParseStrings = contentType == JSON && bodyValue instanceof Map; + Closure parsingClosure = dontParseStrings ? Closure.IDENTITY + : MapConverter.JSON_PARSING_CLOSURE; + return MapConverter.transformValues(bodyValue, ContentUtils.GET_TEST_SIDE, + parsingClosure); + } + return bodyValue; + } + + default String escape(String text) { + return StringEscapeUtils.escapeJava(text); + } + + default String escapeForSimpleTextAssertion(String text) { + return text; + } + + default String postProcessJsonPath(String jsonPath) { + return jsonPath; + } + + default String quotedLongText(Object text) { + return quotedEscapedLongText(escape(text.toString())); + } + + default String quotedEscapedLongText(Object text) { + return "\"" + text.toString() + "\""; + } + + default String quotedShortText(Object text) { + return quotedLongText(text); + } + + default String quotedEscapedShortText(Object text) { + return quotedEscapedLongText(text); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyReader.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyReader.java new file mode 100644 index 0000000000..5a6aa6c6d4 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyReader.java @@ -0,0 +1,90 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.springframework.cloud.contract.spec.internal.FromFileProperty; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.util.Assert; + +class BodyReader { + + private final GeneratedClassMetaData generatedClassMetaData; + + BodyReader(GeneratedClassMetaData generatedClassMetaData) { + this.generatedClassMetaData = generatedClassMetaData; + } + + String readBytesFromFileString(SingleContractMetadata metadata, + FromFileProperty property, CommunicationType side) { + String fileName = byteBodyToAFileForTestMethod(metadata, property, side); + return "fileToBytes(this, \"" + fileName + "\")"; + } + + String readStringFromFileString(SingleContractMetadata metadata, + FromFileProperty property, CommunicationType side) { + return "new String(" + readBytesFromFileString(metadata, property, side) + ")"; + } + + private String byteBodyToAFileForTestMethod(SingleContractMetadata metadata, + FromFileProperty property, CommunicationType side) { + GeneratedClassDataForMethod classDataForMethod = new GeneratedClassDataForMethod( + this.generatedClassMetaData.generatedClassData, metadata.methodName()); + String newFileName = classDataForMethod.getMethodName() + "_" + + side.name().toLowerCase() + "_" + property.fileName(); + java.nio.file.Path parent = classDataForMethod.testClassPath().getParent(); + if (parent == null) { + parent = classDataForMethod.testClassPath(); + } + File newFile = new File(parent.toFile(), newFileName); + // for IDE + try { + Files.write(newFile.toPath(), property.asBytes()); + // for plugin + generatedTestResourcesFileBytes(property, newFile); + } + catch (IOException ex) { + throw new IllegalStateException(ex); + } + return newFileName; + } + + private void generatedTestResourcesFileBytes(FromFileProperty property, File newFile) + throws IOException { + Assert.notNull( + this.generatedClassMetaData.configProperties.getGeneratedTestSourcesDir(), + "No generated test sources directory set"); + Assert.notNull( + this.generatedClassMetaData.configProperties + .getGeneratedTestResourcesDir(), + "No generated test resources directory set"); + Path path = this.generatedClassMetaData.configProperties + .getGeneratedTestSourcesDir().toPath(); + Path relativePath = path.relativize(newFile.toPath()); + File newFileInGeneratedTestSources = new File( + this.generatedClassMetaData.configProperties + .getGeneratedTestResourcesDir(), + relativePath.toString()); + newFileInGeneratedTestSources.getParentFile().mkdirs(); + Files.write(newFileInGeneratedTestSources.toPath(), property.asBytes()); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyThen.java new file mode 100644 index 0000000000..a63ad0e40e --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/BodyThen.java @@ -0,0 +1,37 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.BodyMatchers; +import org.springframework.cloud.contract.spec.internal.DslProperty; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +interface BodyThen { + + default DslProperty requestBody(SingleContractMetadata metadata) { + return metadata.getContract().getRequest().getBody(); + } + + default DslProperty responseBody(SingleContractMetadata metadata) { + return metadata.getContract().getResponse().getBody(); + } + + default BodyMatchers responseBodyMatchers(SingleContractMetadata metadata) { + return metadata.getContract().getResponse().getBodyMatchers(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassAnnotation.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassAnnotation.java new file mode 100644 index 0000000000..bca1cb79bb --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassAnnotation.java @@ -0,0 +1,21 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface ClassAnnotation extends Visitor { + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassAnnotationsBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassAnnotationsBuilder.java new file mode 100644 index 0000000000..214c210239 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassAnnotationsBuilder.java @@ -0,0 +1,55 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +class ClassAnnotationsBuilder { + + private final GeneratedTestClassBuilder parentBuilder; + + private final BlockBuilder builder; + + private final GeneratedClassMetaData metaData; + + ClassAnnotationsBuilder(GeneratedTestClassBuilder generatedTestClassBuilder) { + this.parentBuilder = generatedTestClassBuilder; + this.builder = generatedTestClassBuilder.blockBuilder; + this.metaData = generatedTestClassBuilder.generatedClassMetaData; + } + + ClassAnnotationsBuilder jUnit4() { + this.parentBuilder + .classAnnotations(new JUnit4OrderClassAnnotation(builder, metaData)); + return this; + } + + ClassAnnotationsBuilder jUnit5() { + this.parentBuilder + .classAnnotations(new JUnit5OrderClassAnnotation(builder, metaData)); + return this; + } + + ClassAnnotationsBuilder spock() { + this.parentBuilder + .classAnnotations(new SpockOrderClassAnnotation(builder, metaData)); + return this; + } + + GeneratedTestClassBuilder build() { + return this.parentBuilder; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassBodyBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassBodyBuilder.java new file mode 100644 index 0000000000..eb774c6c6a --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassBodyBuilder.java @@ -0,0 +1,94 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * Builds the body of the class. Sets fields, methods. + * + * @author Olga Maciaszek-Sharma + * @author Marcin Grzejszczak + * @since 2.2.0 + */ +class ClassBodyBuilder { + + private List fields = new LinkedList<>(); + + private SingleMethodBuilder methodBuilder; + + final BlockBuilder blockBuilder; + + final GeneratedClassMetaData generatedClassMetaData; + + private ClassBodyBuilder(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + static ClassBodyBuilder builder(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + return new ClassBodyBuilder(blockBuilder, generatedClassMetaData); + } + + FieldBuilder field() { + return new FieldBuilder(this); + } + + ClassBodyBuilder field(Field field) { + this.fields.add(field); + return this; + } + + ClassBodyBuilder methodBuilder(SingleMethodBuilder methodBuilder) { + this.methodBuilder = methodBuilder; + return this; + } + + /** + * Mutates the {@link BlockBuilder} to generate methods and fields. + * @return block builder with contents of built methods + */ + BlockBuilder build() { + this.blockBuilder.inBraces(() -> { + // @Rule ... + visit(this.fields); + // new line if fields added + this.methodBuilder.build(); + }); + return this.blockBuilder; + } + + void visit(List list) { + List visitors = list.stream().filter(Acceptor::accept) + .collect(Collectors.toList()); + Iterator iterator = visitors.iterator(); + while (iterator.hasNext()) { + Visitor visitor = iterator.next(); + visitor.call(); + this.blockBuilder.addEndingIfNotPresent(); + if (iterator.hasNext()) { + this.blockBuilder.addEmptyLine(); + } + } + } + +} 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 deleted file mode 100644 index 2389ea4a0e..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilder.groovy +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import groovy.transform.CompileStatic -import groovy.transform.PackageScope -import org.apache.commons.logging.Log -import org.apache.commons.logging.LogFactory - -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.config.TestFramework -import org.springframework.cloud.contract.verifier.util.NamesUtil - -/** - * Builds a class. Adds all the imports, static imports etc. - * - * @author Jakub Kubrynski, codearte.io - * - * @since 1.0.0 - */ -@CompileStatic -@PackageScope -class ClassBuilder { - - private static final Log log = LogFactory.getLog(ClassBuilder) - - private static final String SEPARATOR = "_REPLACEME_" - - private final String className - private final String packageName - private final String baseClass - private final List imports = [] - private final List staticImports = [] - private final List rules = [] - private final List fields = [] - private final List methods = [] - private final List classLevelAnnotations = [] - private final TestFramework lang - - private ClassBuilder(String className, String packageName, String baseClass, TestFramework lang) { - this.lang = lang - if (baseClass) { - imports << baseClass - } - this.baseClass = NamesUtil.afterLastDot(baseClass) - this.packageName = packageName - this.className = className - } - - /** - * @return a{@link ClassBuilder} for the given parameters - */ - static ClassBuilder createClass(String className, String classPackage, ContractVerifierConfigProperties properties, - String includedDirectoryRelativePath) { - String baseClassForTests - if (properties.testFramework == TestFramework.SPOCK && !properties.baseClassForTests - && !properties.packageWithBaseClasses - && !properties.baseClassMappings) { - baseClassForTests = 'spock.lang.Specification' - } - else { - baseClassForTests = - retrieveBaseClass(properties, includedDirectoryRelativePath) - } - return new ClassBuilder(className, classPackage, baseClassForTests, properties.testFramework) - } - - protected static String retrieveBaseClass(ContractVerifierConfigProperties properties, String includedDirectoryRelativePath) { - String contractPathAsPackage = includedDirectoryRelativePath. - replace(File.separator, ".") - String contractPackage = includedDirectoryRelativePath. - replace(File.separator, SEPARATOR) - // package mapping takes super precedence - if (properties.baseClassMappings) { - Map.Entry mapping = properties.baseClassMappings. - find { String pattern, String fqn -> - return contractPathAsPackage.matches(pattern) - } - if (log.isDebugEnabled()) { - log.debug("Matching pattern for contract package [${contractPathAsPackage}] with setup ${properties.baseClassMappings} is [${mapping}]") - } - if (mapping) { - return mapping.value - } - } - if (!properties.packageWithBaseClasses) { - return properties.baseClassForTests - } - String generatedClassName = - generateDefaultBaseClassName(contractPackage, properties) - return "${generatedClassName}Base" - } - - private static String generateDefaultBaseClassName(String classPackage, ContractVerifierConfigProperties properties) { - String[] splitPackage = NamesUtil.convertIllegalPackageChars(classPackage). - split(SEPARATOR) - if (splitPackage.size() > 1) { - String last = NamesUtil.capitalize(splitPackage[-1]) - String butLast = NamesUtil.capitalize(splitPackage[-2]) - return "${properties.packageWithBaseClasses}.${butLast}${last}" - } - return "${properties.packageWithBaseClasses}.${NamesUtil.capitalize(splitPackage[0])}" - } - - ClassBuilder addImport(String importToAdd) { - imports << importToAdd - return this - } - - ClassBuilder addImports(List importsToAdd) { - imports.addAll(importsToAdd) - return this - } - - ClassBuilder addStaticImports(List importsToAdd) { - staticImports.addAll(importsToAdd) - return this - } - - ClassBuilder addStaticImport(String importToAdd) { - staticImports << importToAdd - return this - } - - ClassBuilder addMethod(MethodBuilder methodBuilder) { - methods << methodBuilder - return this - } - - ClassBuilder addField(String fieldToAdd) { - fields << appendColonIfJUniTest(fieldToAdd) - return this - } - - ClassBuilder addField(List fieldsToAdd) { - fields.addAll(fieldsToAdd.collect { appendColonIfJUniTest(it) }) - return this - } - - ClassBuilder addRule(String ruleClass) { - imports << ruleClass - rules << NamesUtil.afterLastDot(ruleClass) - return this - } - - String build() { - BlockBuilder clazz = new BlockBuilder("\t") - .addLine("package $packageName$lang.lineSuffix") - .addEmptyLine() - - imports.sort().each { - clazz.addLine("import $it$lang.lineSuffix") - } - if (!imports.empty) { - clazz.addEmptyLine() - } - - staticImports.sort().each { - clazz.addLine("import static $it$lang.lineSuffix") - } - if (!staticImports.empty) { - clazz.addEmptyLine() - } - - classLevelAnnotations.sort().each { - clazz.addLine(it) - } - - def classLine = "${lang.classModifier}class $className" - if (baseClass) { - classLine += " extends $baseClass" - } - clazz.addLine(classLine + ' {') - clazz.addEmptyLine() - - clazz.startBlock() - rules.sort().each { - clazz.addLine("@Rule") - clazz. - addLine("public $it ${NamesUtil.camelCase(it)} = new $it()$lang.lineSuffix") - } - clazz.endBlock() - if (!rules.empty) { - clazz.addEmptyLine() - } - - clazz.startBlock() - fields.sort().each { - clazz.addLine(it) - } - if (!fields.empty) { - clazz.addEmptyLine() - } - clazz.endBlock() - - methods.each { - clazz.addBlock(it) - } - - clazz.addLine('}') - clazz.toString() - } - - void addClassLevelAnnotation(String annotation) { - classLevelAnnotations << annotation - } - - private String appendColonIfJUniTest(String field) { - if (isJUnitType(field)) { - return "$field;" - } - return field - } - - private boolean isJUnitType(String field) { - TestFramework.JUNIT == lang || TestFramework.JUNIT5 == lang && !field.endsWith(';') - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassMetaData.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassMetaData.java new file mode 100644 index 0000000000..2eff623aef --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassMetaData.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface ClassMetaData extends Acceptor { + + ClassMetaData setupLineEnding(); + + ClassMetaData setupLabelPrefix(); + + ClassMetaData packageDefinition(); + + ClassMetaData modifier(); + + ClassMetaData suffix(); + + ClassMetaData parentClass(); + + ClassMetaData className(); + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassVerifier.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassVerifier.java new file mode 100644 index 0000000000..6797119d57 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassVerifier.java @@ -0,0 +1,30 @@ +package org.springframework.cloud.contract.verifier.builder; + +import java.util.List; +import java.util.Map; +import java.util.Set; + +/** + * Used to return the {@link Class} against which the type of the element should be + * verified using instanceof in generated response assertions. + * + * @author Marcin Grzejszczak + * @author Olga Maciaszek-Sharma + * @since 2.1.0 + */ +public interface ClassVerifier { + + default Class classToCheck(Object elementFromBody) { + if (elementFromBody instanceof List) { + return List.class; + } + else if (elementFromBody instanceof Set) { + return Set.class; + } + else if (elementFromBody instanceof Map) { + return Map.class; + } + return elementFromBody.getClass(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CommunicationType.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CommunicationType.java similarity index 80% rename from spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CommunicationType.groovy rename to spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CommunicationType.java index df69cd1d2d..729f45af76 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CommunicationType.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CommunicationType.java @@ -14,9 +14,7 @@ * limitations under the License. */ -package org.springframework.cloud.contract.verifier.builder - -import groovy.transform.CompileStatic +package org.springframework.cloud.contract.verifier.builder; /** * Describes the type of communication @@ -24,7 +22,8 @@ import groovy.transform.CompileStatic * @author Marcin Grzejszczak * @since 2.1.0 */ -@CompileStatic -enum CommunicationType { - REQUEST, RESPONSE, INPUT, OUTPUT +public enum CommunicationType { + + REQUEST, RESPONSE, INPUT, OUTPUT; + } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ComparisonBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ComparisonBuilder.java new file mode 100644 index 0000000000..5e4dc89d68 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ComparisonBuilder.java @@ -0,0 +1,104 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.regex.Pattern; + +import org.apache.commons.text.StringEscapeUtils; + +import static org.apache.commons.text.StringEscapeUtils.escapeJava; + +interface ComparisonBuilder { + + ComparisonBuilder JAVA_HTTP_INSTANCE = () -> RestAssuredBodyParser.INSTANCE; + + ComparisonBuilder JAVA_MESSAGING_INSTANCE = () -> JavaMessagingBodyParser.INSTANCE; + + default String createComparison(Object headerValue) { + if (headerValue instanceof Pattern) { + return matches((Pattern) headerValue); + } + else if (headerValue instanceof Number) { + return isEqualTo((Number) headerValue); + } + String escapedHeader = convertUnicodeEscapesIfRequired(headerValue.toString()); + return isEqualTo(escapedHeader); + } + + default String createUnescapedComparison(Object headerValue) { + if (headerValue instanceof Pattern) { + return createComparison((Pattern) headerValue); + } + else if (headerValue instanceof Number) { + return isEqualTo((Number) headerValue); + } + return isEqualTo(headerValue.toString()); + } + + default String assertThat(String object) { + return "assertThat(" + object + ")"; + } + + default String assertThatIsNotNull(String object) { + return assertThat(object) + isNotNull(); + } + + default String assertThat(String object, Object valueToCompareAgainst) { + return assertThat(object) + createComparison(valueToCompareAgainst); + } + + default String assertThatUnescaped(String object, Object valueToCompareAgainst) { + return assertThat(object) + createUnescapedComparison(valueToCompareAgainst); + } + + default String isEqualTo(String escapedHeaderValue) { + return isEqualToUnquoted(bodyParser().quotedShortText(escapedHeaderValue)); + } + + default String isEqualToUnquoted(String unquoted) { + return ".isEqualTo(" + unquoted + ")"; + } + + default String isEqualTo(Number number) { + return ".isEqualTo(" + number.toString() + ")"; + } + + default String isNotNull() { + return ".isNotNull()"; + } + + default String matches(Pattern pattern) { + String escapedPattern = StringEscapeUtils.escapeJava(pattern.pattern()); + return ".matches(" + bodyParser().quotedEscapedShortText(escapedPattern) + ")"; + } + + default String matches(String pattern) { + return ".matches(" + bodyParser().quotedShortText(pattern) + ")"; + } + + default String matchesEscaped(String pattern) { + return ".matches(" + bodyParser().quotedEscapedShortText(pattern) + ")"; + } + + default String convertUnicodeEscapesIfRequired(String json) { + String unescapedJson = StringEscapeUtils.unescapeJson(json); + return escapeJava(unescapedJson); + } + + BodyParser bodyParser(); + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ContentHelper.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ContentHelper.java new file mode 100644 index 0000000000..f6c451c8b1 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ContentHelper.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.apache.commons.text.StringEscapeUtils; + +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +final class ContentHelper { + + /** + * Depending on the object type extracts the test side values and combines them into a + * String representation. Will not try to guess the type of the value of the header + * (e.g. if it's a JSON). + */ + static String getTestSideForNonBodyValue(Object object) { + if (object instanceof ExecutionProperty) { + return getTestSideValue(object); + } + return quotedAndEscaped( + MapConverter.getTestSideValuesForNonBody(object).toString()); + } + + /** + * Depending on the object type extracts the test side values and combines them into a + * String representation + */ + private static String getTestSideValue(Object object) { + if (object instanceof ExecutionProperty) { + return object.toString(); + } + return '"' + MapConverter.getTestSideValues(object).toString() + '"'; + } + + private static String quotedAndEscaped(String string) { + return '"' + StringEscapeUtils.escapeJava(string) + '"'; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CookieElementProcessor.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CookieElementProcessor.java new file mode 100644 index 0000000000..dbbcb86066 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CookieElementProcessor.java @@ -0,0 +1,85 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.regex.Pattern; + +import org.springframework.cloud.contract.spec.internal.Cookies; +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.spec.internal.NotToEscapePattern; +import org.springframework.cloud.contract.spec.internal.Response; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +interface CookieElementProcessor { + + ComparisonBuilder comparisonBuilder(); + + default void processCookies(SingleContractMetadata metadata) { + Response response = metadata.getContract().getResponse(); + Cookies cookies = response.getCookies(); + cookies.executeForEachCookie(cookie -> processCookieElement(cookie.getKey(), + cookie.getServerValue() instanceof NotToEscapePattern + ? cookie.getServerValue() + : MapConverter.getTestSideValues(cookie.getServerValue()))); + blockBuilder().addEndingIfNotPresent(); + } + + BlockBuilder blockBuilder(); + + default void processCookieElement(String property, Object value) { + if (value instanceof NotToEscapePattern) { + verifyCookieNotNull(property); + blockBuilder() + .addIndented(comparisonBuilder().assertThat(cookieValue(property)) + + comparisonBuilder().matches(((NotToEscapePattern) value) + .getServerValue().pattern().replace("\\", "\\\\"))); + } + else if (value instanceof String || value instanceof Pattern) { + verifyCookieNotNull(property); + blockBuilder().addIndented( + comparisonBuilder().assertThat(cookieValue(property), value)); + } + else if (value instanceof Number) { + verifyCookieNotNull(property); + blockBuilder().addIndented( + comparisonBuilder().assertThat(cookieValue(property), value)); + } + else if (value instanceof ExecutionProperty) { + verifyCookieNotNull(property); + blockBuilder().addIndented( + ((ExecutionProperty) value).insertValue(cookieValue(property))); + + } + else { + // fallback + processCookieElement(property, value.toString()); + } + } + + default void verifyCookieNotNull(String key) { + blockBuilder().addLineWithEnding( + comparisonBuilder().assertThatIsNotNull(cookieKey(key))); + } + + String cookieKey(String key); + + default String cookieValue(String key) { + return cookieKey(key); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CustomImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CustomImports.java new file mode 100644 index 0000000000..d6010d288a --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CustomImports.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +class CustomImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + CustomImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(this.generatedClassMetaData.configProperties.getImports()) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties.getImports() != null + && this.generatedClassMetaData.configProperties.getImports().length > 0; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CustomStaticImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CustomStaticImports.java new file mode 100644 index 0000000000..ff54ba8713 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/CustomStaticImports.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +class CustomStaticImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + CustomStaticImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(this.generatedClassMetaData.configProperties.getStaticImports()) + .forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties.getStaticImports() != null + && this.generatedClassMetaData.configProperties + .getStaticImports().length > 0; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultBaseClassProvider.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultBaseClassProvider.java new file mode 100644 index 0000000000..8c1a0504ec --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultBaseClassProvider.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties; + +interface DefaultBaseClassProvider { + + GeneratedClassMetaData generatedClassMetaData(); + + BaseClassProvider baseClassProvider(); + + default String fqnBaseClass() { + ContractVerifierConfigProperties properties = generatedClassMetaData().configProperties; + String includedDirectoryRelativePath = generatedClassMetaData().includedDirectoryRelativePath; + return baseClassProvider().retrieveBaseClass(properties, + includedDirectoryRelativePath); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultClassMetadata.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultClassMetadata.java new file mode 100644 index 0000000000..0b2121a897 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultClassMetadata.java @@ -0,0 +1,44 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import static org.springframework.cloud.contract.verifier.util.NamesUtil.capitalize; + +interface DefaultClassMetadata extends ClassMetaData, DefaultBaseClassProvider { + + @Override + default ClassMetaData packageDefinition() { + blockBuilder().addLineWithEnding( + "package " + generatedClassMetaData().generatedClassData.classPackage); + return this; + } + + GeneratedClassMetaData generatedClassMetaData(); + + BaseClassProvider baseClassProvider(); + + BlockBuilder blockBuilder(); + + @Override + default ClassMetaData className() { + String className = capitalize( + generatedClassMetaData().generatedClassData.className); + blockBuilder().addAtTheEnd(className); + return this; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultImports.java new file mode 100644 index 0000000000..a4076960e7 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultImports.java @@ -0,0 +1,60 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.util.StringUtils; + +class DefaultImports implements Imports, DefaultBaseClassProvider { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final BaseClassProvider baseClassProvider; + + DefaultImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.baseClassProvider = new BaseClassProvider(); + } + + @Override + public Imports call() { + String fqnBaseClass = fqnBaseClass(); + if (StringUtils.hasText(fqnBaseClass)) { + this.blockBuilder.addLineWithEnding("import " + fqnBaseClass); + } + return this; + } + + @Override + public boolean accept() { + return true; + } + + @Override + public GeneratedClassMetaData generatedClassMetaData() { + return this.generatedClassMetaData; + } + + @Override + public BaseClassProvider baseClassProvider() { + return this.baseClassProvider; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultJsonStaticImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultJsonStaticImports.java new file mode 100644 index 0000000000..5aaae6041a --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultJsonStaticImports.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class DefaultJsonStaticImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { + "com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson" }; + + DefaultJsonStaticImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(metadata -> metadata.getConvertedContractWithMetadata().stream() + .anyMatch(SingleContractMetadata::isJson)); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultStaticImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultStaticImports.java new file mode 100644 index 0000000000..de1958d471 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/DefaultStaticImports.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +class DefaultStaticImports implements Imports { + + private final BlockBuilder blockBuilder; + + private static final String[] IMPORTS = { + "org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat", + "org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*" }; + + DefaultStaticImports(BlockBuilder blockBuilder) { + this.blockBuilder = blockBuilder; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s)); + return this; + } + + @Override + public boolean accept() { + return true; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitAcceptor.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitAcceptor.java new file mode 100644 index 0000000000..1a303644d1 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitAcceptor.java @@ -0,0 +1,27 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestMode; + +interface ExplicitAcceptor { + + default boolean acceptType(GeneratedClassMetaData generatedClassMetaData) { + return generatedClassMetaData.configProperties.getTestMode() == TestMode.EXPLICIT; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitJUnitMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitJUnitMethodBodyBuilder.groovy deleted file mode 100644 index 00efa33fff..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitJUnitMethodBodyBuilder.groovy +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import groovy.transform.PackageScope -import groovy.transform.TypeChecked - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties - -/** - * A {@link JUnitMethodBodyBuilder} implementation that uses Rest Assured in explicit mode - * - * @author Marcin Grzejszczak - * - * @since 1.0.3 - */ -@TypeChecked -@PackageScope -class ExplicitJUnitMethodBodyBuilder extends RestAssuredJUnitMethodBodyBuilder { - - ExplicitJUnitMethodBodyBuilder(Contract stubDefinition, - ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(stubDefinition, configProperties, classDataForMethod) - } - - @Override - protected String returnedResponseType() { - return "Response" - } - - @Override - protected String returnedRequestType() { - return "RequestSpecification" - } - -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRequestGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRequestGiven.java new file mode 100644 index 0000000000..4d167e3a47 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRequestGiven.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class ExplicitRequestGiven implements Given, ExplicitAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + ExplicitRequestGiven(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder.addIndented("RequestSpecification request = given()"); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return acceptType(this.generatedClassMetaData); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitResponseWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitResponseWhen.java new file mode 100644 index 0000000000..40d7ca1a13 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitResponseWhen.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class ExplicitResponseWhen implements When, ExplicitAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + ExplicitResponseWhen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder.addIndented("Response response = given().spec(request)"); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return acceptType(this.generatedClassMetaData); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRestAssuredImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRestAssuredImports.java new file mode 100644 index 0000000000..ef560bc13d --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRestAssuredImports.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestMode; + +class ExplicitRestAssuredImports implements Imports, RestAssuredVerifier { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] REST_ASSURED_2_IMPORTS = { + "com.jayway.restassured.specification.RequestSpecification", + "com.jayway.restassured.response.Response" }; + + private static final String[] REST_ASSURED_3_IMPORTS = { + "io.restassured.specification.RequestSpecification", + "io.restassured.response.Response" }; + + ExplicitRestAssuredImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream( + isRestAssured2Present() ? REST_ASSURED_2_IMPORTS : REST_ASSURED_3_IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestMode() == TestMode.EXPLICIT + && this.generatedClassMetaData.isAnyHttp(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRestAssuredStaticImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRestAssuredStaticImports.java new file mode 100644 index 0000000000..91bdd8e15b --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ExplicitRestAssuredStaticImports.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestMode; + +class ExplicitRestAssuredStaticImports implements Imports, RestAssuredVerifier { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] REST_ASSURED_2_IMPORTS = { + "com.jayway.restassured.RestAssured.*" }; + + private static final String[] REST_ASSURED_3_IMPORTS = { + "io.restassured.RestAssured.*" }; + + ExplicitRestAssuredStaticImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream( + isRestAssured2Present() ? REST_ASSURED_2_IMPORTS : REST_ASSURED_3_IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestMode() == TestMode.EXPLICIT + && this.generatedClassMetaData.isAnyHttp(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Field.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Field.java new file mode 100644 index 0000000000..2e2a2a22eb --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Field.java @@ -0,0 +1,21 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface Field extends Visitor { + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/FieldBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/FieldBuilder.java new file mode 100644 index 0000000000..f761febd0c --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/FieldBuilder.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +class FieldBuilder { + + private final ClassBodyBuilder parentBuilder; + + private final BlockBuilder builder; + + private final GeneratedClassMetaData metaData; + + FieldBuilder(ClassBodyBuilder parentBuilder) { + this.parentBuilder = parentBuilder; + this.builder = parentBuilder.blockBuilder; + this.metaData = parentBuilder.generatedClassMetaData; + } + + FieldBuilder messaging() { + this.parentBuilder.field(new MessagingFields(this.builder, this.metaData)); + return this; + } + + ClassBodyBuilder build() { + return this.parentBuilder; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassDataForMethod.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassDataForMethod.groovy deleted file mode 100644 index 043c7b6c48..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassDataForMethod.groovy +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2013-2018 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License") - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -/** - * @author Marcin Grzejszczak - * @since - */ -class GeneratedClassDataForMethod { - final SingleTestGenerator.GeneratedClassData generatedClassData - final String methodName - - GeneratedClassDataForMethod(SingleTestGenerator.GeneratedClassData generatedClassData, - String methodName) { - this.generatedClassData = generatedClassData - this.methodName = methodName - } - - private SingleTestGenerator.GeneratedClassData assertClassData() { - if (this.generatedClassData == null) { - throw new IllegalStateException("No metadata was found for the generated test class") - } - return this.generatedClassData - } - - String className() { - return assertClassData().className - } - - java.nio.file.Path testClassPath() { - return assertClassData().testClassPath - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassDataForMethod.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassDataForMethod.java new file mode 100644 index 0000000000..8c3f71e397 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassDataForMethod.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.nio.file.Path; + +/** + * POJO that wraps data for a given generated method. + * + * @author Marcin Grzejszczak + * @since 2.1.0 + */ +public class GeneratedClassDataForMethod { + + private final SingleTestGenerator.GeneratedClassData generatedClassData; + + private final String methodName; + + public GeneratedClassDataForMethod( + SingleTestGenerator.GeneratedClassData generatedClassData, + String methodName) { + this.generatedClassData = generatedClassData; + this.methodName = methodName; + } + + private SingleTestGenerator.GeneratedClassData assertClassData() { + if (this.generatedClassData == null) { + throw new IllegalStateException( + "No metadata was found for the generated test class"); + } + return this.generatedClassData; + } + + public String className() { + return assertClassData().className; + } + + public Path testClassPath() { + return assertClassData().testClassPath; + } + + public final SingleTestGenerator.GeneratedClassData getGeneratedClassData() { + return generatedClassData; + } + + public final String getMethodName() { + return methodName; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassMetaData.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassMetaData.java new file mode 100644 index 0000000000..dec5976c0c --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedClassMetaData.java @@ -0,0 +1,84 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Collection; +import java.util.stream.Collectors; + +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties; +import org.springframework.cloud.contract.verifier.file.ContractMetadata; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +/** + * All meta data required to generate a test class. + * + * @author Olga Maciaszek-Sharma + * @author Marcin Grzejszczak + * @since 2.2.0 + */ +class GeneratedClassMetaData { + + final ContractVerifierConfigProperties configProperties; + + final Collection listOfFiles; + + final String includedDirectoryRelativePath; + + final SingleTestGenerator.GeneratedClassData generatedClassData; + + GeneratedClassMetaData(ContractVerifierConfigProperties configProperties, + Collection listOfFiles, + String includedDirectoryRelativePath, + SingleTestGenerator.GeneratedClassData generatedClassData) { + this.configProperties = configProperties; + this.listOfFiles = listOfFiles; + this.includedDirectoryRelativePath = includedDirectoryRelativePath; + this.generatedClassData = generatedClassData; + } + + Collection toSingleContractMetadata() { + return this.listOfFiles.stream() + .flatMap(metadata -> metadata.getConvertedContractWithMetadata().stream()) + .collect(Collectors.toList()); + } + + boolean isAnyJson() { + return toSingleContractMetadata().stream() + .anyMatch(SingleContractMetadata::isJson); + } + + boolean isAnyIgnored() { + return toSingleContractMetadata().stream() + .anyMatch(SingleContractMetadata::isIgnored); + } + + boolean isAnyXml() { + return toSingleContractMetadata().stream() + .anyMatch(SingleContractMetadata::isXml); + } + + boolean isAnyHttp() { + return toSingleContractMetadata().stream() + .anyMatch(SingleContractMetadata::isHttp); + } + + boolean isAnyMessaging() { + return toSingleContractMetadata().stream() + .anyMatch(SingleContractMetadata::isMessaging); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassVerifier.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedTestClass.java similarity index 59% rename from spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassVerifier.groovy rename to spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedTestClass.java index c03555dc26..6f1001493c 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ClassVerifier.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedTestClass.java @@ -14,28 +14,25 @@ * limitations under the License. */ -package org.springframework.cloud.contract.verifier.builder +package org.springframework.cloud.contract.verifier.builder; /** - * Used to return the {@link Class} against which the type of the element should be verified - * using instanceof in generated response assertions. + * Contents of the generated test. * - * @author Marcin Grzejszczak * @author Olga Maciaszek-Sharma - * @since 2.1.0 + * @author Marcin Grzejszczak + * @since 2.2.0 */ -trait ClassVerifier { +public class GeneratedTestClass { - Class classToCheck(Object elementFromBody) { - switch (elementFromBody.getClass()) { - case List: - return List - case Set: - return Set - case Map: - return Map - default: - return elementFromBody.class - } + final BlockBuilder blockBuilder; + + GeneratedTestClass(BlockBuilder blockBuilder) { + this.blockBuilder = blockBuilder; } + + public String asClassString() { + return this.blockBuilder.toString(); + } + } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedTestClassBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedTestClassBuilder.java new file mode 100644 index 0000000000..6a1f6173d6 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedTestClassBuilder.java @@ -0,0 +1,182 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +/** + * A generated test class consists of the class meta data (e.g. packages, imports) fields + * and methods. The latter are generated via the {@link ClassBodyBuilder}. + * + * @author Olga Maciaszek-Sharma + * @author Marcin Grzejszczak + * @since 2.2.0 + */ +class GeneratedTestClassBuilder { + + private List metaData = new LinkedList<>(); + + private List imports = new LinkedList<>(); + + private List staticImports = new LinkedList<>(); + + private List annotations = new LinkedList<>(); + + private ClassBodyBuilder classBodyBuilder; + + final BlockBuilder blockBuilder; + + final GeneratedClassMetaData generatedClassMetaData; + + private GeneratedTestClassBuilder(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + static GeneratedTestClassBuilder builder(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + return new GeneratedTestClassBuilder(blockBuilder, generatedClassMetaData); + } + + GeneratedTestClassBuilder metaData(ClassMetaData metaData) { + this.metaData.add(metaData); + return this; + } + + MetaDataBuilder metaData() { + return new MetaDataBuilder(this); + } + + GeneratedTestClassBuilder metaData(ClassMetaData... metaData) { + return metaData(Arrays.asList(metaData)); + } + + GeneratedTestClassBuilder metaData(List metaData) { + this.metaData.addAll(metaData); + return this; + } + + ImportsBuilder imports() { + return new ImportsBuilder(this); + } + + GeneratedTestClassBuilder imports(Imports imports) { + this.imports.add(imports); + return this; + } + + GeneratedTestClassBuilder imports(Imports... imports) { + return imports(Arrays.asList(imports)); + } + + GeneratedTestClassBuilder imports(List imports) { + this.imports.addAll(imports); + return this; + } + + GeneratedTestClassBuilder staticImports(Imports imports) { + this.staticImports.add(imports); + return this; + } + + GeneratedTestClassBuilder staticImports(Imports... imports) { + return staticImports(Arrays.asList(imports)); + } + + GeneratedTestClassBuilder staticImports(List imports) { + this.staticImports.addAll(imports); + return this; + } + + ClassAnnotationsBuilder classAnnotations() { + return new ClassAnnotationsBuilder(this); + } + + GeneratedTestClassBuilder classAnnotations(ClassAnnotation... annotations) { + List classAnnotations = Arrays.asList(annotations); + this.annotations.addAll(classAnnotations); + return this; + } + + GeneratedTestClassBuilder classBodyBuilder(ClassBodyBuilder classBodyBuilder) { + this.classBodyBuilder = classBodyBuilder; + return this; + } + + /** + * From a matching {@link ClassMetaData} given the present input data, builds a + * generated test class. + * @return generated test class + */ + GeneratedTestClass build() { + // picks a matching class meta data + ClassMetaData classMetaData = this.metaData.stream().filter(Acceptor::accept) + .findFirst().orElseThrow(() -> new IllegalStateException( + "There is no matching class meta data")); + classMetaData.setupLineEnding().setupLabelPrefix() + // package com.example + .packageDefinition(); + // \n + this.blockBuilder.addEmptyLine(); + // import ... \n + visit(this.imports); + // import static ... \n + visit(this.staticImports); + // @Test ... \n + visitWithNoEnding(this.annotations); + // @formatter:off + // public + this.blockBuilder.append(classMetaData::modifier) + // class + .appendWithSpace("class") + // Foo + .appendWithSpace(classMetaData::className) + // Spec + .append(classMetaData::suffix) + // extends Parent + .appendWithSpace(classMetaData::parentClass); + // public class FooSpec extends Parent + // @formatter:on + this.classBodyBuilder.build(); + return new GeneratedTestClass(this.blockBuilder); + } + + void visit(List list) { + visit(list, true); + } + + void visitWithNoEnding(List list) { + visit(list, false); + } + + private void visit(List list, boolean addEnding) { + List elements = list.stream().filter(Acceptor::accept) + .collect(Collectors.toList()); + elements.forEach(OurCallable::call); + if (addEnding) { + this.blockBuilder.addEndingIfNotPresent(); + } + if (!elements.isEmpty()) { + this.blockBuilder.addEmptyLine(); + } + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericBinaryBodyThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericBinaryBodyThen.java new file mode 100644 index 0000000000..527f29a768 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericBinaryBodyThen.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.FromFileProperty; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class GenericBinaryBodyThen implements Then { + + private final BlockBuilder blockBuilder; + + private final BodyAssertionLineCreator bodyAssertionLineCreator; + + private final BodyParser bodyParser; + + private final ComparisonBuilder comparisonBuilder; + + GenericBinaryBodyThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData, + BodyParser bodyParser, ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.comparisonBuilder = comparisonBuilder; + this.bodyAssertionLineCreator = new BodyAssertionLineCreator(blockBuilder, + metaData, bodyParser.byteArrayString(), this.comparisonBuilder); + this.bodyParser = bodyParser; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + Object responseBody = this.bodyParser.responseBody(metadata).getServerValue(); + byteResponseBodyCheck(metadata, (FromFileProperty) responseBody); + return this; + } + + private void byteResponseBodyCheck(SingleContractMetadata metadata, + FromFileProperty convertedResponseBody) { + this.bodyAssertionLineCreator.appendBodyAssertionLine(metadata, "", + convertedResponseBody); + this.blockBuilder.addEndingIfNotPresent(); + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Object responseBody = this.bodyParser.responseBody(metadata).getServerValue(); + if (!(responseBody instanceof FromFileProperty)) { + return false; + } + return ((FromFileProperty) responseBody).isByte(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericHttpBodyThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericHttpBodyThen.java new file mode 100644 index 0000000000..7520a5febc --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericHttpBodyThen.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.template.HandlebarsTemplateProcessor; +import org.springframework.cloud.contract.verifier.template.TemplateProcessor; + +class GenericHttpBodyThen implements Then, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final BodyParser bodyParser; + + private final TemplateProcessor templateProcessor; + + private final ComparisonBuilder comparisonBuilder; + + private final List thens = new LinkedList<>(); + + GenericHttpBodyThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData, + BodyParser bodyParser, ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.bodyParser = bodyParser; + this.comparisonBuilder = comparisonBuilder; + this.templateProcessor = new HandlebarsTemplateProcessor(); + this.thens.addAll(Arrays.asList( + new GenericBinaryBodyThen(blockBuilder, metaData, this.bodyParser, + comparisonBuilder), + new GenericTextBodyThen(blockBuilder, metaData, this.bodyParser, + this.comparisonBuilder), + new GenericJsonBodyThen(blockBuilder, metaData, this.bodyParser, + this.comparisonBuilder), + new GenericXmlBodyThen(blockBuilder, this.bodyParser))); + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + endBodyBlock(this.blockBuilder); + this.blockBuilder.addEmptyLine(); + startBodyBlock(this.blockBuilder, "and:"); + Request request = metadata.getContract().getRequest(); + this.thens.stream().filter(then -> then.accept(metadata)) + .forEach(then -> then.apply(metadata)); + String newBody = this.templateProcessor.transform(request, + this.blockBuilder.toString()); + this.blockBuilder.updateContents(newBody); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.getContract().getResponse().getBody() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericJsonBodyThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericJsonBodyThen.java new file mode 100644 index 0000000000..60956a5938 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericJsonBodyThen.java @@ -0,0 +1,220 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; + +import org.apache.commons.text.StringEscapeUtils; + +import org.springframework.cloud.contract.spec.ContractTemplate; +import org.springframework.cloud.contract.spec.internal.BodyMatchers; +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.template.HandlebarsTemplateProcessor; +import org.springframework.cloud.contract.verifier.template.TemplateProcessor; +import org.springframework.cloud.contract.verifier.util.ContentType; +import org.springframework.cloud.contract.verifier.util.MapConverter; +import org.springframework.util.StringUtils; + +import static org.springframework.cloud.contract.verifier.util.ContentType.DEFINED; +import static org.springframework.cloud.contract.verifier.util.ContentType.FORM; +import static org.springframework.cloud.contract.verifier.util.ContentType.JSON; +import static org.springframework.cloud.contract.verifier.util.ContentType.TEXT; + +class GenericJsonBodyThen implements Then { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final BodyParser bodyParser; + + private final BodyAssertionLineCreator bodyAssertionLineCreator; + + private final TemplateProcessor templateProcessor; + + private final ContractTemplate contractTemplate; + + private final ComparisonBuilder comparisonBuilder; + + GenericJsonBodyThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData, + BodyParser bodyParser, ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.bodyParser = bodyParser; + this.comparisonBuilder = comparisonBuilder; + this.bodyAssertionLineCreator = new BodyAssertionLineCreator(blockBuilder, + metaData, this.bodyParser.byteArrayString(), this.comparisonBuilder); + this.generatedClassMetaData = metaData; + this.templateProcessor = new HandlebarsTemplateProcessor(); + this.contractTemplate = new HandlebarsTemplateProcessor(); + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + BodyMatchers bodyMatchers = this.bodyParser.responseBodyMatchers(metadata); + Object convertedResponseBody = this.bodyParser.convertResponseBody(metadata); + ContentType contentType = metadata.getOutputTestContentType(); + if (TEXT != contentType && FORM != contentType && DEFINED != contentType) { + boolean dontParseStrings = contentType == JSON + && convertedResponseBody instanceof Map; + Function parsingClosure = dontParseStrings ? Function.identity() + : MapConverter.JSON_PARSING_FUNCTION; + convertedResponseBody = MapConverter.getTestSideValues(convertedResponseBody, + parsingClosure); + } + else { + convertedResponseBody = StringEscapeUtils + .escapeJava(convertedResponseBody.toString()); + } + addJsonBodyVerification(metadata, convertedResponseBody, bodyMatchers); + return this; + } + + private void addJsonBodyVerification(SingleContractMetadata contractMetadata, + Object responseBody, BodyMatchers bodyMatchers) { + JsonBodyVerificationBuilder jsonBodyVerificationBuilder = new JsonBodyVerificationBuilder( + this.generatedClassMetaData.configProperties, this.templateProcessor, + this.contractTemplate, contractMetadata.getContract(), + Optional.of(this.blockBuilder.getLineEnding()), + bodyParser::postProcessJsonPath); + // TODO: Refactor spock from should comment out bdd blocks + Object convertedResponseBody = jsonBodyVerificationBuilder + .addJsonResponseBodyCheck(this.blockBuilder, responseBody, bodyMatchers, + this.bodyParser.responseAsString(), + this.generatedClassMetaData.configProperties + .getTestFramework() != TestFramework.SPOCK); + if (!(convertedResponseBody instanceof Map + || convertedResponseBody instanceof List)) { + simpleTextResponseBodyCheck(contractMetadata, convertedResponseBody); + } + processBodyElement("", "", convertedResponseBody); + } + + private void processBodyElement(String oldProp, String property, Object value) { + String propDiff = subtract(property, oldProp); + String prop = wrappedWithBracketsForDottedProp(propDiff); + String mergedProp = StringUtils.hasText(property) ? oldProp + "." + prop : ""; + if (value instanceof ExecutionProperty) { + processBodyElement(mergedProp, (ExecutionProperty) value); + } + else if (value instanceof Map.Entry) { + processBodyElement(mergedProp, (Map.Entry) value); + } + else if (value instanceof Map) { + processBodyElement(mergedProp, (Map) value); + } + else if (value instanceof List) { + processBodyElement(mergedProp, (List) value); + } + } + + private void processBodyElement(String property, ExecutionProperty exec) { + this.blockBuilder.addLineWithEnding(exec.insertValue(this.bodyParser + .postProcessJsonPath("parsedJson.read(\"$" + property + "\")"))); + } + + private void processBodyElement(String property, Map.Entry entry) { + processBodyElement(property, getMapKeyReferenceString(property, entry), + entry.getValue()); + } + + private void processBodyElement(String property, Map map) { + map.entrySet().forEach(o -> processBodyElement(property, (Map.Entry) o)); + } + + private void processBodyElement(String property, List list) { + Iterator iterator = list.iterator(); + int index = -1; + while (iterator.hasNext()) { + Object listElement = iterator.next(); + index = index + 1; + String prop = getPropertyInListString(property, index); + processBodyElement(property, prop, listElement); + } + } + + private String getPropertyInListString(String property, Integer listIndex) { + return property + "[" + listIndex + "]"; + } + + private String getMapKeyReferenceString(String property, Map.Entry entry) { + return provideProperJsonPathNotation(property) + "." + entry.getKey(); + } + + private String provideProperJsonPathNotation(String property) { + return property.replaceAll("(get\\(\\\\\")(.*)(\\\\\"\\))", "$2"); + } + + private String wrappedWithBracketsForDottedProp(String key) { + String remindingKey = trailingKey(key); + if (remindingKey.contains(".")) { + return "['" + remindingKey + "']"; + } + return remindingKey; + } + + private String trailingKey(String key) { + if (key.startsWith(".")) { + return key.substring(1); + } + return key; + } + + private String subtract(String self, String text) { + int index = self.indexOf(text); + if (index == -1) { + return self; + } + int end = index + text.length(); + if (self.length() > end) { + return self.substring(0, index) + self.substring(end); + } + return self.substring(0, index); + } + + private void simpleTextResponseBodyCheck(SingleContractMetadata metadata, + Object convertedResponseBody) { + this.blockBuilder.addLineWithEnding( + getSimpleResponseBodyString(this.bodyParser.responseAsString())); + this.bodyAssertionLineCreator.appendBodyAssertionLine(metadata, "", + convertedResponseBody); + this.blockBuilder.addEndingIfNotPresent(); + } + + private String getSimpleResponseBodyString(String responseString) { + return "String responseBody = " + responseString + + this.blockBuilder.getLineEnding(); + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + ContentType outputTestContentType = metadata.getOutputTestContentType(); + return JSON == outputTestContentType + || mostLikelyJson(outputTestContentType, metadata); + } + + private boolean mostLikelyJson(ContentType outputTestContentType, + SingleContractMetadata metadata) { + return DEFINED == outputTestContentType && metadata.evaluatesToJson(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericTextBodyThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericTextBodyThen.java new file mode 100644 index 0000000000..1cff55005c --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericTextBodyThen.java @@ -0,0 +1,79 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.FromFileProperty; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.ContentType; + +import static org.springframework.cloud.contract.verifier.util.ContentType.JSON; +import static org.springframework.cloud.contract.verifier.util.ContentType.XML; + +class GenericTextBodyThen implements Then { + + private final BlockBuilder blockBuilder; + + private final BodyAssertionLineCreator bodyAssertionLineCreator; + + private final BodyParser bodyParser; + + private final ComparisonBuilder comparisonBuilder; + + GenericTextBodyThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData, + BodyParser bodyParser, ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.bodyParser = bodyParser; + this.comparisonBuilder = comparisonBuilder; + this.bodyAssertionLineCreator = new BodyAssertionLineCreator(blockBuilder, + metaData, this.bodyParser.byteArrayString(), this.comparisonBuilder); + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + Object convertedResponseBody = this.bodyParser.convertResponseBody(metadata); + if (convertedResponseBody instanceof String) { + convertedResponseBody = this.bodyParser + .escapeForSimpleTextAssertion(convertedResponseBody.toString()); + } + simpleTextResponseBodyCheck(metadata, convertedResponseBody); + return this; + } + + private void simpleTextResponseBodyCheck(SingleContractMetadata metadata, + Object convertedResponseBody) { + this.blockBuilder.addLineWithEnding( + getSimpleResponseBodyString(this.bodyParser.responseAsString())); + this.bodyAssertionLineCreator.appendBodyAssertionLine(metadata, "", + convertedResponseBody); + this.blockBuilder.addEndingIfNotPresent(); + } + + private String getSimpleResponseBodyString(String responseString) { + return "String responseBody = " + responseString + + this.blockBuilder.getLineEnding(); + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + ContentType outputTestContentType = metadata.getOutputTestContentType(); + return outputTestContentType != JSON && outputTestContentType != XML + && this.bodyParser.responseBody(metadata) != null + && !(this.bodyParser.responseBody(metadata) + .getServerValue() instanceof FromFileProperty); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericXmlBodyThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericXmlBodyThen.java new file mode 100644 index 0000000000..a217b236be --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GenericXmlBodyThen.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Optional; + +import org.springframework.cloud.contract.spec.internal.BodyMatchers; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.ContentType; + +import static org.springframework.cloud.contract.verifier.util.ContentType.XML; + +class GenericXmlBodyThen implements Then { + + private final BlockBuilder blockBuilder; + + private final BodyParser bodyParser; + + GenericXmlBodyThen(BlockBuilder blockBuilder, BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.bodyParser = bodyParser; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + BodyMatchers bodyMatchers = this.bodyParser.responseBodyMatchers(metadata); + Object convertedResponseBody = this.bodyParser.convertResponseBody(metadata); + XmlBodyVerificationBuilder xmlBodyVerificationBuilder = new XmlBodyVerificationBuilder( + metadata.getContract(), Optional.of(this.blockBuilder.getLineEnding())); + xmlBodyVerificationBuilder.addXmlResponseBodyCheck(this.blockBuilder, + convertedResponseBody, bodyMatchers, this.bodyParser.responseAsString(), + true); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + ContentType outputTestContentType = metadata.getOutputTestContentType(); + return XML == outputTestContentType; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Given.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Given.java new file mode 100644 index 0000000000..22ee5bea69 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Given.java @@ -0,0 +1,21 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface Given extends MethodVisitor { + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyBodyParser.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyBodyParser.java new file mode 100644 index 0000000000..b5d56947db --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyBodyParser.java @@ -0,0 +1,88 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.apache.commons.text.StringEscapeUtils; + +import org.springframework.cloud.contract.verifier.template.TemplateProcessor; + +interface GroovyBodyParser extends BodyParser { + + @Override + default String convertUnicodeEscapesIfRequired(String json) { + return StringEscapeUtils.unescapeEcmaScript(json); + } + + @Override + default String postProcessJsonPath(String jsonPath) { + if (templateProcessor().containsTemplateEntry(jsonPath)) { + return jsonPath; + } + return jsonPath.replace("$", "\\$"); + } + + TemplateProcessor templateProcessor(); + + @Override + default String escape(String text) { + return text.replaceAll("\\n", "\\\\n"); + } + + @Override + default String escapeForSimpleTextAssertion(String text) { + return escape(text); + } + + @Override + default String quotedShortText(Object text) { + String string = text.toString(); + if (text instanceof Number) { + return string; + } + else if (string.contains("'") || string.contains("\"")) { + return quotedLongText(text); + } + return "'" + groovyEscapedString(text.toString()) + "'"; + } + + @Override + default String quotedEscapedShortText(Object text) { + String string = text.toString(); + if (text instanceof Number) { + return string; + } + else if (string.contains("'") || string.contains("\"")) { + return quotedEscapedLongText(text); + } + return "'" + text.toString() + "'"; + } + + @Override + default String quotedEscapedLongText(Object text) { + return "'''" + text.toString() + "'''"; + } + + @Override + default String quotedLongText(Object text) { + return "'''" + groovyEscapedString(text) + "'''"; + } + + default String groovyEscapedString(Object text) { + return escape(text.toString()).replaceAll("\\\\\"", "\""); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyClassMetaData.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyClassMetaData.java new file mode 100644 index 0000000000..228c1a1dcf --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyClassMetaData.java @@ -0,0 +1,108 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties; +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.util.StringUtils; + +class GroovyClassMetaData implements ClassMetaData, DefaultClassMetadata { + + private final BlockBuilder blockBuilder; + + private final BaseClassProvider baseClassProvider = new BaseClassProvider(); + + private final GeneratedClassMetaData generatedClassMetaData; + + GroovyClassMetaData(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public ClassMetaData setupLineEnding() { + return this; + } + + @Override + public ClassMetaData setupLabelPrefix() { + return this; + } + + @Override + public ClassMetaData suffix() { + String suffix = StringUtils.hasText( + this.generatedClassMetaData.configProperties.getNameSuffixForTests()) + ? this.generatedClassMetaData.configProperties + .getNameSuffixForTests() + : "Spec"; + if (!this.blockBuilder.endsWith(suffix)) { + this.blockBuilder.addAtTheEnd(suffix); + } + return this; + } + + @Override + public ClassMetaData modifier() { + return this; + } + + @Override + public ClassMetaData packageDefinition() { + this.blockBuilder.addLineWithEnding( + "package " + this.generatedClassMetaData.generatedClassData.classPackage); + return this; + } + + @Override + public ClassMetaData parentClass() { + ContractVerifierConfigProperties properties = generatedClassMetaData().configProperties; + String includedDirectoryRelativePath = generatedClassMetaData().includedDirectoryRelativePath; + String baseClass = baseClassProvider().retrieveBaseClass(properties, + includedDirectoryRelativePath); + baseClass = StringUtils.hasText(baseClass) ? baseClass : "Specification"; + int lastIndexOf = baseClass.lastIndexOf("."); + if (lastIndexOf > 0) { + baseClass = baseClass.substring(lastIndexOf + 1); + } + blockBuilder().append("extends ").append(baseClass).append(" "); + return this; + } + + @Override + public GeneratedClassMetaData generatedClassMetaData() { + return this.generatedClassMetaData; + } + + @Override + public BaseClassProvider baseClassProvider() { + return this.baseClassProvider; + } + + @Override + public BlockBuilder blockBuilder() { + return this.blockBuilder; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyComparisonBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyComparisonBuilder.java new file mode 100644 index 0000000000..7e2f63f74e --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/GroovyComparisonBuilder.java @@ -0,0 +1,68 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.regex.Pattern; + +import org.apache.commons.text.StringEscapeUtils; + +interface GroovyComparisonBuilder extends ComparisonBuilder { + + ComparisonBuilder SPOCK_HTTP_INSTANCE = (GroovyComparisonBuilder) () -> SpockRestAssuredBodyParser.INSTANCE; + + ComparisonBuilder JAXRS_HTTP_INSTANCE = (GroovyComparisonBuilder) () -> JaxRsBodyParser.INSTANCE; + + ComparisonBuilder SPOCK_MESSAGING_INSTANCE = (GroovyComparisonBuilder) () -> SpockMessagingBodyParser.INSTANCE; + + @Override + default String assertThat(String object) { + return object; + } + + @Override + default String isEqualToUnquoted(String unquoted) { + return " == " + unquoted; + } + + @Override + default String isEqualTo(Number number) { + return " == " + number.toString(); + } + + @Override + default String matches(String pattern) { + return matchesEscaped(bodyParser().quotedShortText(pattern)); + } + + @Override + default String matches(Pattern pattern) { + String escapedPattern = StringEscapeUtils.escapeJava(pattern.pattern()); + return matchesEscaped(escapedPattern); + } + + @Override + default String matchesEscaped(String pattern) { + return " ==~ java.util.regex.Pattern.compile(" + + bodyParser().quotedEscapedShortText(pattern) + ")"; + } + + @Override + default String isNotNull() { + return " != null"; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/HttpSpockMethodRequestProcessingBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/HttpSpockMethodRequestProcessingBodyBuilder.groovy deleted file mode 100644 index 528ba4a045..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/HttpSpockMethodRequestProcessingBodyBuilder.groovy +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import java.util.regex.Pattern - -import groovy.transform.PackageScope -import groovy.transform.TypeChecked - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.Cookie -import org.springframework.cloud.contract.spec.internal.ExecutionProperty -import org.springframework.cloud.contract.spec.internal.Header -import org.springframework.cloud.contract.spec.internal.NotToEscapePattern -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.util.MapConverter - -/** - * A {@link SpockMethodRequestProcessingBodyBuilder} implementation that uses MockMvc to send requests. - * - * @since 1.0.0 - */ -@PackageScope -@TypeChecked -class HttpSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProcessingBodyBuilder { - - HttpSpockMethodRequestProcessingBodyBuilder(Contract stubDefinition, - ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(stubDefinition, configProperties, classDataForMethod) - } - - @Override - protected void validateResponseCodeBlock(BlockBuilder bb) { - bb.addLine("response.statusCode == $response.status.serverValue") - } - - @Override - protected void validateResponseHeadersBlock(BlockBuilder bb) { - response.headers?.executeForEachHeader { Header header -> - processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ? - header.serverValue : - MapConverter.getTestSideValues(header.serverValue)) - } - } - - @Override - protected void validateResponseCookiesBlock(BlockBuilder bb) { - response.cookies?.executeForEachCookie { Cookie cookie -> - processCookieElement(bb, cookie.key, cookie.serverValue instanceof NotToEscapePattern ? - cookie.serverValue : - MapConverter.getTestSideValues(cookie.serverValue)) - } - } - - @Override - protected String getResponseAsString() { - return 'response.body.asString()' - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) { - if (value instanceof NotToEscapePattern) { - blockBuilder.addLine("response.header('$property') " - + - "${patternComparison(((NotToEscapePattern) value).serverValue.pattern().replace("\\", "\\\\"))}") - } - else { - // fallback - processHeaderElement(blockBuilder, property, value.toString()) - } - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, Object value) { - if (value instanceof NotToEscapePattern) { - blockBuilder.addLine("response.cookie('$key') " - + - "${patternComparison(((NotToEscapePattern) value).serverValue.pattern().replace("\\", "\\\\"))}") - } - else { - processCookieElement(blockBuilder, key, value.toString()) - } - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number number) { - blockBuilder.addLine("response.header('$property') == ${number}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder.addLine("${exec.insertValue("response.header(\'$property\')")}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) { - blockBuilder. - addLine("response.header('$property') ${convertHeaderComparison(value)}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern value) { - blockBuilder. - addLine("response.header('$property') ${convertHeaderComparison(value)}") - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) { - blockBuilder.addLine("response.cookie('$key') != null") - blockBuilder. - addLine("response.cookie('$key') ${convertCookieComparison(pattern)}") - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) { - blockBuilder.addLine("response.cookie('$key') != null") - blockBuilder.addLine("response.cookie('$key') ${convertCookieComparison(value)}") - } - - // #273 - should escape $ for Groovy since it will try to make it a GString - @Override - protected String postProcessJsonPathCall(String jsonPath) { - if (templateProcessor.containsTemplateEntry(jsonPath)) { - return jsonPath - } - return jsonPath.replace('$', '\\$') - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Imports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Imports.java new file mode 100644 index 0000000000..229cae4b8d --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Imports.java @@ -0,0 +1,21 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface Imports extends Visitor { + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ImportsBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ImportsBuilder.java new file mode 100644 index 0000000000..fbcbe18c09 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/ImportsBuilder.java @@ -0,0 +1,105 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +class ImportsBuilder { + + private final GeneratedTestClassBuilder parentBuilder; + + private final BlockBuilder builder; + + private final GeneratedClassMetaData metaData; + + ImportsBuilder(GeneratedTestClassBuilder generatedTestClassBuilder) { + this.parentBuilder = generatedTestClassBuilder; + this.builder = generatedTestClassBuilder.blockBuilder; + this.metaData = generatedTestClassBuilder.generatedClassMetaData; + } + + ImportsBuilder defaultImports() { + this.parentBuilder.imports(new DefaultImports(builder, metaData)); + this.parentBuilder.staticImports(new DefaultStaticImports(builder)); + return this; + } + + ImportsBuilder custom() { + this.parentBuilder.imports(new CustomImports(builder, metaData)); + this.parentBuilder.staticImports(new CustomStaticImports(builder, metaData)); + return this; + } + + ImportsBuilder json() { + this.parentBuilder.imports(new JsonImports(builder, metaData), + new JsonPathImports(builder, metaData)); + this.parentBuilder.staticImports(new DefaultJsonStaticImports(builder, metaData)); + return this; + } + + ImportsBuilder xml() { + this.parentBuilder.imports(new XmlImports(builder, metaData)); + return this; + } + + ImportsBuilder jUnit4() { + this.parentBuilder.imports(new JUnit4Imports(builder, metaData), + new JUnit4IgnoreImports(builder, metaData), + new JUnit4OrderImports(builder, metaData)); + return this; + } + + ImportsBuilder jUnit5() { + this.parentBuilder.imports(new JUnit5Imports(builder, metaData), + new JUnit5IgnoreImports(builder, metaData), + new JUnit5OrderImports(builder, metaData)); + return this; + } + + ImportsBuilder spock() { + this.parentBuilder.imports(new SpockImports(builder, metaData), + new SpockIgnoreImports(builder, metaData), + new SpockOrderImports(builder, metaData)); + return this; + } + + ImportsBuilder messaging() { + this.parentBuilder.imports(new MessagingImports(builder, metaData)); + this.parentBuilder.staticImports(new MessagingStaticImports(builder, metaData)); + return this; + } + + ImportsBuilder restAssured() { + this.parentBuilder.imports(new MockMvcRestAssuredImports(builder, metaData), + new ExplicitRestAssuredImports(builder, metaData), + new WebTestClientRestAssuredImports(builder, metaData)); + this.parentBuilder.staticImports( + new MockMvcRestAssuredStaticImports(builder, metaData), + new ExplicitRestAssuredStaticImports(builder, metaData), + new WebTestClientRestAssured3StaticImports(builder, metaData)); + return this; + } + + ImportsBuilder jaxRs() { + this.parentBuilder.imports(new JaxRsImports(builder, metaData)); + this.parentBuilder.staticImports(new JaxRsStaticImports(builder, metaData)); + return this; + } + + GeneratedTestClassBuilder build() { + return this.parentBuilder; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4IgnoreImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4IgnoreImports.java new file mode 100644 index 0000000000..03786f1768 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4IgnoreImports.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JUnit4IgnoreImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + JUnit4IgnoreImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + this.blockBuilder.addLineWithEnding("import org.junit.Ignore"); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT + && this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(metadata -> metadata.isIgnored() + || metadata.getConvertedContractWithMetadata().stream() + .anyMatch(SingleContractMetadata::isIgnored)); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4IgnoreMethodAnnotation.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4IgnoreMethodAnnotation.java new file mode 100644 index 0000000000..6708edd1c5 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4IgnoreMethodAnnotation.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JUnit4IgnoreMethodAnnotation implements MethodAnnotations { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] ANNOTATIONS = { "@Ignore" }; + + JUnit4IgnoreMethodAnnotation(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public MethodVisitor apply( + SingleContractMetadata singleContractMetadata) { + Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented); + return this; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT + && this.generatedClassMetaData.isAnyIgnored(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4Imports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4Imports.java new file mode 100644 index 0000000000..0145eccc80 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4Imports.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; + +class JUnit4Imports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "org.junit.Test", "org.junit.Rule" }; + + JUnit4Imports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4MethodAnnotation.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4MethodAnnotation.java new file mode 100644 index 0000000000..9d58f6d7f4 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4MethodAnnotation.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JUnit4MethodAnnotation implements MethodAnnotations { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] ANNOTATIONS = { "@Test" }; + + JUnit4MethodAnnotation(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT; + } + + @Override + public MethodVisitor apply( + SingleContractMetadata singleContractMetadata) { + Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented); + return this; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4OrderClassAnnotation.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4OrderClassAnnotation.java new file mode 100644 index 0000000000..363cdf4c95 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4OrderClassAnnotation.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; + +class JUnit4OrderClassAnnotation implements ClassAnnotation { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] ANNOTATIONS = { + "@FixMethodOrder(MethodSorters.NAME_ASCENDING)" }; + + JUnit4OrderClassAnnotation(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public ClassAnnotation call() { + Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT + && this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(meta -> meta.getOrder() != null); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4OrderImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4OrderImports.java new file mode 100644 index 0000000000..01e0c629ea --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit4OrderImports.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; + +class JUnit4OrderImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "org.junit.FixMethodOrder", + "org.junit.runners.MethodSorters" }; + + JUnit4OrderImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT + && this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(meta -> meta.getOrder() != null); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5IgnoreImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5IgnoreImports.java new file mode 100644 index 0000000000..f02af7ac81 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5IgnoreImports.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JUnit5IgnoreImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + JUnit5IgnoreImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + this.blockBuilder.addLineWithEnding("import org.junit.jupiter.api.Disabled"); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT5 + && this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(metadata -> metadata.isIgnored() + || metadata.getConvertedContractWithMetadata().stream() + .anyMatch(SingleContractMetadata::isIgnored)); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5IgnoreMethodAnnotation.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5IgnoreMethodAnnotation.java new file mode 100644 index 0000000000..9c426cbe90 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5IgnoreMethodAnnotation.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JUnit5IgnoreMethodAnnotation implements MethodAnnotations { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] ANNOTATIONS = { "@Disabled" }; + + JUnit5IgnoreMethodAnnotation(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public MethodVisitor apply( + SingleContractMetadata singleContractMetadata) { + Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented); + return this; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT5 + && this.generatedClassMetaData.isAnyIgnored(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5Imports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5Imports.java new file mode 100644 index 0000000000..5c522664fb --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5Imports.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; + +class JUnit5Imports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "org.junit.jupiter.api.Test", + "org.junit.jupiter.api.extension.ExtendWith" }; + + JUnit5Imports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT5; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5MethodAnnotation.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5MethodAnnotation.java new file mode 100644 index 0000000000..6463abfdff --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5MethodAnnotation.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JUnit5MethodAnnotation implements MethodAnnotations { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] ANNOTATIONS = { "@Test" }; + + JUnit5MethodAnnotation(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public MethodVisitor apply( + SingleContractMetadata singleContractMetadata) { + Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented); + return this; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT5; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5OrderClassAnnotation.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5OrderClassAnnotation.java new file mode 100644 index 0000000000..00697d79bf --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5OrderClassAnnotation.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; + +class JUnit5OrderClassAnnotation implements ClassAnnotation { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] ANNOTATIONS = { + "@FixMethodOrder(MethodSorters.NAME_ASCENDING)" }; + + JUnit5OrderClassAnnotation(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public ClassAnnotation call() { + // Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented); + throw new UnsupportedOperationException( + "Not implemented yet in JUnit5 - https://github.com/junit-team/junit5/issues/48"); + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT5 + && this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(meta -> meta.getOrder() != null); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5OrderImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5OrderImports.java new file mode 100644 index 0000000000..b474331dc0 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnit5OrderImports.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; + +class JUnit5OrderImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "" }; + + JUnit5OrderImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + // Arrays.stream(IMPORTS) + // .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + throw new UnsupportedOperationException( + "Not implemented yet in JUnit5 - https://github.com/junit-team/junit5/issues/48"); + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT5 + && this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(meta -> meta.getOrder() != null); + } + +} 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 deleted file mode 100644 index bf21c7364c..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMessagingMethodBodyBuilder.groovy +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import java.util.regex.Pattern - -import groovy.json.StringEscapeUtils -import groovy.transform.PackageScope -import groovy.transform.TypeChecked - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.Cookie -import org.springframework.cloud.contract.spec.internal.ExecutionProperty -import org.springframework.cloud.contract.spec.internal.FromFileProperty -import org.springframework.cloud.contract.spec.internal.Header -import org.springframework.cloud.contract.spec.internal.Input -import org.springframework.cloud.contract.spec.internal.NamedProperty -import org.springframework.cloud.contract.spec.internal.NotToEscapePattern -import org.springframework.cloud.contract.spec.internal.RegexProperty -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.util.MapConverter - -import static groovy.json.StringEscapeUtils.escapeJava -import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT - -/** - * Builds a JUnit method for messaging - * - * Do not change to {@code @CompileStatic} since it's using double dispatch. - * - * @author Marcin Grzejszczak - * @author Jakub Kubrynski, codearte.io - * @author Tim Ysewyn - * - * @since 1.0.0 - */ -@PackageScope -@TypeChecked -class JUnitMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { - - JUnitMessagingMethodBodyBuilder(Contract stubDefinition, - ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(stubDefinition, configProperties, classDataForMethod) - } - - @Override - protected String getInputString(Input request) { - if (request.triggeredBy) { - return request.triggeredBy.executionCommand - } - return "contractVerifierMessaging.send(inputMessage, \"${request.messageFrom.serverValue}\")" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, Object value) { - return "" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, String value) { - return "" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, Pattern value) { - return "" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, ExecutionProperty value) { - return "" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) { - if (value.isByte()) { - return "assertThat(response.getPayloadAsByteArray()).isEqualTo(" + - readBytesFromFileString(value, CommunicationType.RESPONSE) + ")" - } - return getResponseBodyPropertyComparisonString(property, value.asString()) - } - - @Override - protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder.addLine("${exec.insertValue("parsedJson.read('\\\$$property')")}") - } - - @Override - protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) { - processBodyElement(blockBuilder, property, property + "." + entry.key, entry.value) - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) { - blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();") - blockBuilder. - addLine("assertThat(response.getHeader(\"$property\").toString()).${createHeaderComparison(value)}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) { - blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();") - blockBuilder. - addLine("assertThat(response.getHeader(\"$property\")).isEqualTo(${value});") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) { - blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();") - blockBuilder. - addLine("assertThat(response.getHeader(\"$property\").toString()).${createHeaderComparison(pattern)}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder.addLine("assertThat(response.getHeader(\"$property\")).isNotNull();") - blockBuilder. - addLine("${exec.insertValue("response.getHeader(\"$property\").toString()")};") - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) { - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, GString value) { - - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) { - } - - @Override - protected void validateResponseCodeBlock(BlockBuilder bb) { - - } - - @Override - protected void validateResponseHeadersBlock(BlockBuilder bb) { - bb.addLine("""ContractVerifierMessage response = contractVerifierMessaging.receive(${ - sentToValue(outputMessage.sentTo.serverValue) - });""") - bb.addLine("""assertThat(response).isNotNull();""") - outputMessage.headers?.executeForEachHeader { Header header -> - processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ? - header.serverValue : - MapConverter.getTestSideValues(header.serverValue)) - } - } - - @Override - protected void validateResponseCookiesBlock(BlockBuilder bb) { - } - - private String sentToValue(Object sentTo) { - if (sentTo instanceof ExecutionProperty) { - return ((ExecutionProperty) sentTo).executionCommand - } - return '"' + sentTo.toString() + '"' - } - - @Override - protected String getResponseAsString() { - return 'contractVerifierObjectMapper.writeValueAsString(response.getPayload())' - } - - @Override - protected String addCommentSignIfRequired(String baseString) { - return "// $baseString" - } - - @Override - protected boolean shouldCommentOutBDDBlocks() { - return true - } - - @Override - protected BlockBuilder addColonIfRequired(BlockBuilder blockBuilder) { - blockBuilder.addAtTheEnd(JUNIT.lineSuffix) - return blockBuilder - } - - @Override - protected Optional lineSuffix() { - return Optional.of(JUNIT.lineSuffix) - } - - @Override - protected String getPropertyInListString(String property, Integer listIndex) { - return "$property[$listIndex]" ?: '' - } - - @Override - protected String convertUnicodeEscapesIfRequired(String json) { - return StringEscapeUtils.unescapeJavaScript(json) - } - - @Override - protected String getSimpleResponseBodyString(String responseString) { - return "Object responseBody = ($responseString);" - } - - @Override - protected String getInputString() { - String request = 'ContractVerifierMessage inputMessage = contractVerifierMessaging.create(' - if (inputMessage.messageBody) { - request = "${request}${getBodyAsString()}" - } - if (inputMessage.messageHeaders) { - request = "${request}${indentHeadersString()}" - } - inputMessage.messageHeaders?.executeForEachHeader { Header header -> - request = "${request}${indentedHeaderString(header)}" - } - return finishIndentation(request) - } - - private String indentHeadersString() { - return "\t\t\t\t, headers()" - } - - private String indentedHeaderString(Header header) { - return "\n\t\t\t\t\t\t${getHeaderString(header)}" - } - - private String finishIndentation(String text) { - return "${text}\n\t\t\t)" - } - - @Override - protected String getHeaderString(Header header) { - return ".header(${getTestSideValue(header.name)}, ${getTestSideValue(header.serverValue)})" - } - - @Override - protected String getCookieString(Cookie cookie) { - return "" - } - - @Override - protected String getBodyString(Object body) { - return "" - } - - @Override - protected String getMultipartFileParameterContent(String propertyName, NamedProperty propertyValue) { - return "" - } - - @Override - protected String getParameterString(Map.Entry parameter) { - return "" - } - - protected String convertHeaderComparison(String headerValue) { - return "" - } - - protected String convertHeaderComparison(Pattern headerValue) { - return "" - } - - protected String convertHeaderComparison(RegexProperty headerValue) { - return convertHeaderComparison(headerValue.pattern) - } - - protected String createHeaderComparison(Object headerValue) { - String escapedHeader = convertUnicodeEscapesIfRequired("$headerValue") - return "isEqualTo(\"$escapedHeader\");" - } - - protected String createHeaderComparison(Pattern headerValue) { - String escapedJavaHeader = escapeJava(headerValue.pattern()) - return "matches(\"$escapedJavaHeader\");" - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy deleted file mode 100644 index a95f9f70cf..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodBodyBuilder.groovy +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - - -import java.util.regex.Pattern - -import groovy.json.StringEscapeUtils -import groovy.transform.PackageScope -import groovy.transform.TypeChecked - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.Cookie -import org.springframework.cloud.contract.spec.internal.ExecutionProperty -import org.springframework.cloud.contract.spec.internal.FromFileProperty -import org.springframework.cloud.contract.spec.internal.Header -import org.springframework.cloud.contract.spec.internal.NamedProperty -import org.springframework.cloud.contract.spec.internal.Request -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.util.RegexpBuilders - -import static groovy.json.StringEscapeUtils.escapeJava -import static org.apache.commons.text.StringEscapeUtils.escapeJava -import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT -import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT5 -import static org.springframework.cloud.contract.verifier.util.ContentUtils.getJavaMultipartFileParameterContent - -/** - * Root class for JUnit method building - * - * Do not change to {@code @CompileStatic} since it's using double dispatch. - * - * @author Jakub Kubrynski, codearte.io - * @author Olga Maciaszek-Sharma, codearte.io - * - * @since 1.0.0 - */ -@TypeChecked -@PackageScope -abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder { - - JUnitMethodBodyBuilder(Contract stubDefinition, ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(stubDefinition, configProperties, classDataForMethod) - } - - @Override - protected String getResponseAsString() { - return "response.getBody().asString()" - } - - @Override - protected String addCommentSignIfRequired(String baseString) { - return "// $baseString" - } - - @Override - protected boolean shouldCommentOutBDDBlocks() { - return true - } - - @Override - protected BlockBuilder addColonIfRequired(BlockBuilder blockBuilder) { - blockBuilder.addAtTheEnd(JUNIT.lineSuffix) - return blockBuilder - } - - @Override - protected Optional lineSuffix() { - return Optional.of(JUNIT5.lineSuffix) - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, String value) { - return "assertThat(responseBody${property}).isEqualTo(\"${value}\")" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, Object value) { - return getResponseBodyPropertyComparisonString(property, value as String) - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, Pattern value) { - return "assertThat(responseBody${property}).${createBodyComparison(value)}" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, ExecutionProperty value) { - return value.insertValue("responseBody${property}") - } - - @Override - protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder.addLine("${exec.insertValue("parsedJson.read(\"\$$property\")")};") - } - - @Override - protected String getPropertyInListString(String property, Integer listIndex) { - return "${property}[$listIndex]" ?: '' - } - - @Override - protected String convertUnicodeEscapesIfRequired(String json) { - String unescapedJson = StringEscapeUtils.unescapeJavaScript(json) - return escapeJava(unescapedJson) - } - - @Override - protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) { - processBodyElement(blockBuilder, property, - getMapKeyReferenceString(property, entry), entry.value) - } - - private String getMapKeyReferenceString(String property, Map.Entry entry) { - return provideProperJsonPathNotation(property) + "." + entry.key - } - - private String provideProperJsonPathNotation(String property) { - return property.replaceAll('(get\\(\\\\")(.*)(\\\\"\\))', '$2') - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) { - if (value.isByte()) { - return "assertThat(response.getBody().asByteArray()).isEqualTo(" + - readBytesFromFileString(value, CommunicationType.RESPONSE) + ")" - } - return getResponseBodyPropertyComparisonString(property, value.asString()) - } - - @Override - protected String getSimpleResponseBodyString(String responseString) { - return "String responseBody = $responseString;" - } - - @Override - protected String getInputString(Request request) { - return "${returnedResponseType()} response = given().spec(request)" - } - - protected String returnedResponseType() { - return "ResponseOptions" - } - - @Override - protected String getInputString() { - return "${returnedRequestType()} request = given()" - } - - protected String returnedRequestType() { - return "MockMvcRequestSpecification" - } - - @Override - protected String getHeaderString(Header header) { - return ".header(${getTestSideForNonBodyValue(header.name)}, ${getTestSideForNonBodyValue(header.serverValue)})" - } - - @Override - protected String getCookieString(Cookie cookie) { - return ".cookie(${getTestSideForNonBodyValue(cookie.key)}, ${getTestSideForNonBodyValue(cookie.serverValue)})" - } - - @Override - protected String getBodyString(Object body) { - String value - if (body instanceof ExecutionProperty) { - value = body.toString() - } - else if (body instanceof FromFileProperty) { - FromFileProperty fileProperty = (FromFileProperty) body - value = fileProperty.isByte() ? - readBytesFromFileString(fileProperty, CommunicationType.REQUEST) : - readStringFromFileString(fileProperty, CommunicationType.REQUEST) - } - else { - String escaped = escapeRequestSpecialChars(body.toString()) - value = "\"$escaped\"" - } - return ".body($value)" - } - - @Override - protected String getMultipartFileParameterContent(String propertyName, NamedProperty propertyValue) { - return getJavaMultipartFileParameterContent(propertyName, propertyValue, { FromFileProperty fileProp -> - readBytesFromFileString(fileProp, CommunicationType.REQUEST) - }) - } - - @Override - protected String getParameterString(Map.Entry parameter) { - return """.param("${escapeJava(parameter.key)}", "${ - escapeJava(parameter.value as String) - }")""" - } - - protected String createHeaderComparison(Object headerValue) { - String escapedHeader = convertUnicodeEscapesIfRequired("$headerValue") - return "isEqualTo(\"$escapedHeader\");" - } - - protected String createHeaderComparison(Pattern headerValue) { - return createMatchesMethod(escapeJava(headerValue.pattern())) + ";" - } - - protected String createBodyComparison(Pattern bodyValue) { - String patternAsString = bodyValue.pattern() - return createMatchesMethod(RegexpBuilders. - buildGStringRegexpForTestSide(patternAsString)) + ";" - } - - protected String createCookieComparison(Object cookieValue) { - String escapedCookie = convertUnicodeEscapesIfRequired("$cookieValue") - return "isEqualTo(\"$escapedCookie\");" - } - - protected String createCookieComparison(Pattern cookieValue) { - return createMatchesMethod(escapeJava(cookieValue.pattern())) + ";" - } - - private String buildEscapedMatchesMethod(Pattern escapedValue) { - String escapedHeader = convertUnicodeEscapesIfRequired("$escapedValue") - return createMatchesMethod(escapedHeader) - } - - protected String createMatchesMethod(String pattern) { - return "matches(\"$pattern\")" - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodMetadata.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodMetadata.java new file mode 100644 index 0000000000..2b29dc4fe8 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JUnitMethodMetadata.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JUnitMethodMetadata implements MethodMetadata { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData metaData; + + private final NameProvider nameProvider = new NameProvider(); + + JUnitMethodMetadata(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.metaData = metaData; + } + + @Override + public MethodMetadata name(SingleContractMetadata metaData) { + this.blockBuilder.addAtTheEnd(this.nameProvider.methodName(metaData)); + return this; + } + + @Override + public MethodMetadata modifier() { + this.blockBuilder.addIndented("public"); + return this; + } + + @Override + public MethodMetadata returnType() { + this.blockBuilder.append("void"); + return this; + } + + @Override + public boolean accept() { + return this.metaData.configProperties.getTestFramework() != TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaClassMetaData.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaClassMetaData.java new file mode 100644 index 0000000000..6b72228ecb --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaClassMetaData.java @@ -0,0 +1,103 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.util.StringUtils; + +class JavaClassMetaData implements ClassMetaData, DefaultClassMetadata { + + private final BlockBuilder blockBuilder; + + private final BaseClassProvider baseClassProvider = new BaseClassProvider(); + + private final GeneratedClassMetaData generatedClassMetaData; + + JavaClassMetaData(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public ClassMetaData modifier() { + this.blockBuilder.append("public"); + return this; + } + + @Override + public ClassMetaData suffix() { + String suffix = StringUtils.hasText( + this.generatedClassMetaData.configProperties.getNameSuffixForTests()) + ? this.generatedClassMetaData.configProperties + .getNameSuffixForTests() + : "Test"; + if (!this.blockBuilder.endsWith(suffix)) { + this.blockBuilder.addAtTheEnd(suffix); + } + return this; + } + + @Override + public ClassMetaData setupLineEnding() { + this.blockBuilder.setupLineEnding(";"); + return this; + } + + @Override + public ClassMetaData setupLabelPrefix() { + this.blockBuilder.setupLabelPrefix("// "); + return this; + } + + @Override + public GeneratedClassMetaData generatedClassMetaData() { + return this.generatedClassMetaData; + } + + @Override + public BaseClassProvider baseClassProvider() { + return this.baseClassProvider; + } + + @Override + public BlockBuilder blockBuilder() { + return this.blockBuilder; + } + + @Override + public ClassMetaData parentClass() { + String baseClass = fqnBaseClass(); + if (StringUtils.hasText(baseClass)) { + int lastIndexOf = baseClass.lastIndexOf("."); + if (lastIndexOf > 0) { + baseClass = baseClass.substring(lastIndexOf + 1); + } + blockBuilder().append("extends ").append(baseClass).append(" "); + } + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT + || this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.JUNIT5; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaJaxRsThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaJaxRsThen.java new file mode 100644 index 0000000000..f086bc0d62 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaJaxRsThen.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JavaJaxRsThen extends JaxRsThen { + + private final GeneratedClassMetaData metaData; + + JavaJaxRsThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, JaxRsBodyParser.INSTANCE, + ComparisonBuilder.JAVA_HTTP_INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() != TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaJaxRsWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaJaxRsWhen.java new file mode 100644 index 0000000000..0a2ea28beb --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaJaxRsWhen.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JavaJaxRsWhen extends JaxRsWhen { + + private final GeneratedClassMetaData metaData; + + JavaJaxRsWhen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, JaxRsBodyParser.INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() != TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingBodyParser.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingBodyParser.java new file mode 100644 index 0000000000..832c2db54c --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingBodyParser.java @@ -0,0 +1,24 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface JavaMessagingBodyParser extends MessagingBodyParser { + + BodyParser INSTANCE = new JavaMessagingBodyParser() { + }; + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingGiven.java new file mode 100644 index 0000000000..83fc53e7ad --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingGiven.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JavaMessagingGiven extends MessagingGiven { + + private final GeneratedClassMetaData generatedClassMetaData; + + JavaMessagingGiven(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, JavaMessagingBodyParser.INSTANCE); + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return super.accept(metadata) && this.generatedClassMetaData.configProperties + .getTestFramework() != TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingWithBodyThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingWithBodyThen.java new file mode 100644 index 0000000000..4e3c801ddf --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaMessagingWithBodyThen.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JavaMessagingWithBodyThen extends MessagingWithBodyThen { + + private final GeneratedClassMetaData metaData; + + JavaMessagingWithBodyThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, + ComparisonBuilder.JAVA_MESSAGING_INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() != TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredGiven.java new file mode 100644 index 0000000000..ff4884f61f --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredGiven.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JavaRestAssuredGiven extends RestAssuredGiven { + + private final GeneratedClassMetaData metaData; + + JavaRestAssuredGiven(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, RestAssuredBodyParser.INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() != TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredThen.java new file mode 100644 index 0000000000..62c53cbb6e --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredThen.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JavaRestAssuredThen extends RestAssuredThen { + + private final GeneratedClassMetaData metaData; + + JavaRestAssuredThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, RestAssuredBodyParser.INSTANCE, + ComparisonBuilder.JAVA_HTTP_INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() != TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredWhen.java new file mode 100644 index 0000000000..acfa7765c6 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaRestAssuredWhen.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JavaRestAssuredWhen extends RestAssuredWhen { + + private final GeneratedClassMetaData metaData; + + JavaRestAssuredWhen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, RestAssuredBodyParser.INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() != TestFramework.SPOCK; + } + +} 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 deleted file mode 100644 index df6637345f..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaTestGenerator.groovy +++ /dev/null @@ -1,232 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import java.lang.invoke.MethodHandles - -import groovy.transform.Canonical -import groovy.transform.CompileStatic -import groovy.transform.EqualsAndHashCode -import groovy.transform.PackageScope -import org.apache.commons.logging.Log -import org.apache.commons.logging.LogFactory - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.verifier.builder.imports.HttpImportProvider -import org.springframework.cloud.contract.verifier.builder.imports.MessagingImportProvider -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.file.ContractMetadata - -import static org.springframework.cloud.contract.verifier.builder.imports.BaseImportProvider.getImports -import static org.springframework.cloud.contract.verifier.builder.imports.BaseImportProvider.getRuleImport -import static org.springframework.cloud.contract.verifier.builder.imports.BaseImportProvider.getStaticImports -import static org.springframework.cloud.contract.verifier.util.NamesUtil.capitalize - -/** - * Builds a single test for the given {@link ContractVerifierConfigProperties properties} - * - * @since 1.1.0 - */ -@CompileStatic -class JavaTestGenerator implements SingleTestGenerator { - - private static final Log log = LogFactory.getLog(MethodHandles.lookup().lookupClass()) - - private static final String JSON_ASSERT_STATIC_IMPORT = 'com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson' - private static final String JSON_ASSERT_CLASS = 'com.toomuchcoding.jsonassert.JsonAssertion' - @Deprecated - // TODO: Remove in next major - private static final String REST_ASSURED_2_0_CLASS = 'com.jayway.restassured.RestAssured' - - @PackageScope - ClassPresenceChecker checker = new ClassPresenceChecker() - - @Override - String buildClass(ContractVerifierConfigProperties configProperties, Collection listOfFiles, String includedDirectoryRelativePath, GeneratedClassData generatedClassData) { - String className = generatedClassData.className - String classPackage = generatedClassData.classPackage - ClassBuilder clazz = ClassBuilder.createClass( - capitalize(className), classPackage, configProperties, includedDirectoryRelativePath) - if (configProperties.imports) { - configProperties.imports.each { String it -> - clazz.addImport(it) - } - } - if (configProperties.staticImports) { - configProperties.staticImports.each { String it -> - clazz.addStaticImport(it) - } - } - if (isScenarioClass(listOfFiles)) { - clazz.addImports(configProperties.testFramework.getOrderAnnotationImports()) - clazz.addClassLevelAnnotation(configProperties.testFramework. - getOrderAnnotation()) - } - // FIXME: change during Hoxton refactoring: we should only add either Json or Xml imports and not both - addJsonPathRelatedImports(clazz) - addXPathRelatedImports(clazz) - processContractFiles(listOfFiles, configProperties, clazz, generatedClassData) - return clazz.build() - } - - @Override - String buildClass(ContractVerifierConfigProperties configProperties, Collection listOfFiles, String className, String classPackage, String includedDirectoryRelativePath) { - return buildClass(configProperties, listOfFiles, includedDirectoryRelativePath, new GeneratedClassData(className, classPackage, null)) - } - - private void processContractFiles(Collection listOfFiles, ContractVerifierConfigProperties configProperties, ClassBuilder clazz, GeneratedClassData generatedClassData) { - Map contracts = mapContractsToTheirTestTypes(listOfFiles) - boolean conditionalImportsAdded = false - boolean toIgnore = listOfFiles.find { it.ignored } - contracts.each { ParsedDsl key, TestType value -> - if (!conditionalImportsAdded) { - clazz.addImports(getImports(configProperties.testFramework)) - clazz.addStaticImports(getStaticImports(configProperties.testFramework)) - if (contracts.values().contains(TestType.HTTP)) { - addHttpRelatedEntries(clazz, configProperties) - } - if (configProperties.ruleClassForTests) { - addRule(configProperties, clazz) - } - if (contracts.values().contains(TestType.MESSAGING)) { - addMessagingRelatedEntries(clazz) - } - conditionalImportsAdded = true - } - toIgnore = toIgnore ? true : key.groovyDsl.ignored - clazz.addMethod(MethodBuilder.createTestMethod(key.contract, key.stubsFile, - key.groovyDsl, configProperties, generatedClassData)) - } - - if (toIgnore) { - clazz.addImport(configProperties.testFramework.getIgnoreClass()) - } - } - - private void addRule(ContractVerifierConfigProperties configProperties, ClassBuilder clazz) { - clazz.addImport(getRuleImport(configProperties.testFramework)) - if (configProperties.testFramework.annotationLevelRules()) { - clazz.addClassLevelAnnotation(configProperties.testFramework - .getRuleAnnotation(configProperties.ruleClassForTests)) - } - else { - clazz.addRule(configProperties.ruleClassForTests) - } - } - - private void addHttpRelatedEntries(ClassBuilder clazz, ContractVerifierConfigProperties configProperties) { - HttpImportProvider httpImportProvider = new HttpImportProvider( - getRestAssuredPackage()) - clazz.addImports(httpImportProvider. - getImports(configProperties.testFramework, configProperties.testMode)) - clazz.addStaticImports(httpImportProvider. - getStaticImports(configProperties.testFramework, configProperties.testMode)) - } - - // TODO for 2.2: leave only RestAssured 3 - private String getRestAssuredPackage() { - boolean restAssured2Present = this.checker.isClassPresent(REST_ASSURED_2_0_CLASS) - String restAssuredPackage = restAssured2Present ? 'com.jayway.restassured' : 'io.restassured' - if (log.isDebugEnabled()) { - log.debug("Rest Assured version 2.x found [${restAssured2Present}]") - } - return restAssuredPackage - } - - @Override - String fileExtension(ContractVerifierConfigProperties properties) { - return properties.testFramework.classExtension - } - - private Map mapContractsToTheirTestTypes(Collection listOfFiles) { - Map dsls = [:] - listOfFiles.each { ContractMetadata metadata -> - File stubsFile = metadata.path.toFile() - if (log.isDebugEnabled()) { - log.debug("Stub content from file [${stubsFile.text}]") - } - Collection stubContents = metadata.convertedContract - Map entries = stubContents. - collectEntries { Contract stubContent -> - TestType testType = (stubContent.input || stubContent.outputMessage) ? TestType.MESSAGING : TestType.HTTP - return [(new ParsedDsl(metadata, stubContent, stubsFile)): testType] - } - dsls.putAll(entries) - } - return dsls - } - - @Canonical - @EqualsAndHashCode(includeFields = true) - @CompileStatic - private static class ParsedDsl { - ContractMetadata contract - Contract groovyDsl - File stubsFile - } - - private static enum TestType { - MESSAGING, HTTP - } - - private boolean isScenarioClass(Collection listOfFiles) { - return listOfFiles.find({ it.order != null }) != null - } - - private void addJsonPathRelatedImports(ClassBuilder clazz) { - clazz.addImports(['com.jayway.jsonpath.DocumentContext', - 'com.jayway.jsonpath.JsonPath', - ]) - if (this.checker.isClassPresent(JSON_ASSERT_CLASS)) { - clazz.addStaticImport(JSON_ASSERT_STATIC_IMPORT) - } - } - - private void addXPathRelatedImports(ClassBuilder clazz) { - clazz.addImports(['javax.xml.parsers.DocumentBuilder', - 'javax.xml.parsers.DocumentBuilderFactory', - 'org.w3c.dom.Document', - 'org.xml.sax.InputSource', - 'java.io.StringReader']) - } - - private void addMessagingRelatedEntries(ClassBuilder clazz) { - clazz.addField(['@Inject ContractVerifierMessaging contractVerifierMessaging', - '@Inject ContractVerifierObjectMapper contractVerifierObjectMapper' - ]) - clazz.addImports(MessagingImportProvider.getImports()) - clazz.addStaticImports(MessagingImportProvider.getStaticImports()) - } -} - -class ClassPresenceChecker { - - private static final Log log = LogFactory.getLog(ClassPresenceChecker) - - boolean isClassPresent(String className) { - try { - Class.forName(className) - return true - } - catch (ClassNotFoundException ex) { - if (log.isDebugEnabled()) { - log.debug("[${className}] is not present on classpath. Will not add a static import.") - } - return false - } - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaTestGenerator.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaTestGenerator.java new file mode 100644 index 0000000000..dc92640c0d --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JavaTestGenerator.java @@ -0,0 +1,126 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Collection; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties; +import org.springframework.cloud.contract.verifier.file.ContractMetadata; + +/** + * Builds a single test for the given {@link ContractVerifierConfigProperties properties} + * + * @since 1.1.0 + */ +public class JavaTestGenerator implements SingleTestGenerator { + + private static final Log log = LogFactory.getLog(JavaTestGenerator.class); + + @Override + public String buildClass(ContractVerifierConfigProperties properties, + Collection listOfFiles, String className, + String classPackage, String includedDirectoryRelativePath) { + throw new UnsupportedOperationException("Deprecated method"); + } + + @Override + public String buildClass(ContractVerifierConfigProperties properties, + Collection listOfFiles, + String includedDirectoryRelativePath, GeneratedClassData generatedClassData) { + BlockBuilder builder = new BlockBuilder("\t"); + GeneratedClassMetaData metaData = new GeneratedClassMetaData(properties, + listOfFiles, includedDirectoryRelativePath, generatedClassData); + return classAsString(builder, metaData); + } + + private String classAsString(BlockBuilder builder, GeneratedClassMetaData metaData) { + SingleMethodBuilder methodBuilder = singleMethodBuilder(builder, metaData); + ClassBodyBuilder bodyBuilder = classBodyBuilder(builder, metaData, methodBuilder); + GeneratedTestClass generatedTestClass = generatedTestClass(builder, metaData, + bodyBuilder); + return generatedTestClass.asClassString(); + } + + GeneratedTestClass generatedTestClass(BlockBuilder builder, + GeneratedClassMetaData metaData, ClassBodyBuilder bodyBuilder) { + // @formatter:off + return GeneratedTestClassBuilder.builder(builder, metaData) + .classBodyBuilder(bodyBuilder) + .metaData() + .java() + .groovy() + .build() + .imports() + .defaultImports() + .custom() + .json() + .jUnit4() + .jUnit5() + .spock() + .xml() + .messaging() + .restAssured() + .jaxRs() + .build() + .classAnnotations() + .jUnit4() + .jUnit5() + .spock() + .build() + .build(); + // @formatter:on + } + + ClassBodyBuilder classBodyBuilder(BlockBuilder builder, + GeneratedClassMetaData metaData, SingleMethodBuilder methodBuilder) { + // @formatter:off + return ClassBodyBuilder.builder(builder, metaData) + .field() + .messaging() + .build() + .methodBuilder(methodBuilder); + // @formatter:on + } + + SingleMethodBuilder singleMethodBuilder(BlockBuilder builder, + GeneratedClassMetaData metaData) { + // @formatter:off + return SingleMethodBuilder.builder(builder, metaData) + .methodAnnotation() + .jUnit4() + .jUnit5() + .spock() + .build() + .methodMetadata() + .jUnit() + .spock() + .build() + .restAssured() + .jaxRs() + .messaging(); + // @formatter:on + } + + @Override + public String fileExtension(ContractVerifierConfigProperties properties) { + return properties.getTestFramework().getClassExtension(); + } + +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsAcceptor.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsAcceptor.java new file mode 100644 index 0000000000..1b7e00838c --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsAcceptor.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestMode; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +interface JaxRsAcceptor { + + default boolean acceptType(GeneratedClassMetaData generatedClassMetaData, + SingleContractMetadata singleContractMetadata) { + return generatedClassMetaData.configProperties + .getTestMode() == TestMode.JAXRSCLIENT && singleContractMetadata.isHttp(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsBodyParser.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsBodyParser.java new file mode 100644 index 0000000000..a5a771afc3 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsBodyParser.java @@ -0,0 +1,36 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface JaxRsBodyParser extends BodyParser { + + JaxRsBodyParser INSTANCE = new JaxRsBodyParser() { + }; + + default String readEntity() { + return "response.readEntity(String.class)"; + } + + default String responseAsString() { + return "responseAsString"; + } + + default String byteArrayString() { + return "response.readEntity(byte[].class)"; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientJUnitMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientJUnitMethodBodyBuilder.groovy deleted file mode 100644 index 5bb567577d..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientJUnitMethodBodyBuilder.groovy +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import java.util.regex.Pattern - -import groovy.transform.PackageScope -import groovy.transform.TypeChecked - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.Cookie -import org.springframework.cloud.contract.spec.internal.DslProperty -import org.springframework.cloud.contract.spec.internal.ExecutionProperty -import org.springframework.cloud.contract.spec.internal.FromFileProperty -import org.springframework.cloud.contract.spec.internal.Header -import org.springframework.cloud.contract.spec.internal.NotToEscapePattern -import org.springframework.cloud.contract.spec.internal.QueryParameter -import org.springframework.cloud.contract.spec.internal.QueryParameters -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.util.MapConverter - -import static org.springframework.cloud.contract.verifier.config.TestFramework.JUNIT - -/** - * JaxRs implementation of the {@link JUnitMethodBodyBuilder}. Knows how to build - * a test method for JaxRs. - * - * Do not change to {@code @CompileStatic} since it's using double dispatch. - * - * @author Olga Maciaszek-Sharma, codearte.io - * - * @since 1.0.0 - */ -@TypeChecked -@PackageScope -class JaxRsClientJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder { - - JaxRsClientJUnitMethodBodyBuilder(Contract stubDefinition, - ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(stubDefinition, configProperties, classDataForMethod) - } - - @Override - protected void given(BlockBuilder bb) {} - - @Override - protected void givenBlock(BlockBuilder bb) { - } - - @Override - protected void when(BlockBuilder bb) { - bb.addLine("Response response = webTarget") - bb.indent() - - appendUrlPathAndQueryParameters(bb) - appendRequestWithRequiredResponseContentType(bb) - appendHeaders(bb) - appendCookies(bb) - appendMethodAndBody(bb) - bb.addAtTheEnd(JUNIT.lineSuffix) - - bb.unindent() - - bb.addEmptyLine() - if (expectsResponseBody()) { - bb.addLine("String responseAsString = response.readEntity(String.class);") - } - } - - protected void appendUrlPathAndQueryParameters(BlockBuilder bb) { - if (request.url) { - bb.addLine(".path(${concreteUrl(request.url)})") - appendQueryParams(request.url.queryParameters, bb) - } - else if (request.urlPath) { - bb.addLine(".path(${concreteUrl(request.urlPath)})") - appendQueryParams(request.urlPath.queryParameters, bb) - } - } - - protected String concreteUrl(DslProperty url) { - Object testSideUrl = MapConverter.getTestSideValues(url) - if (!(testSideUrl instanceof ExecutionProperty)) { - return '"' + testSideUrl.toString() + '"' - } - return testSideUrl.toString() - } - - private void appendQueryParams(QueryParameters queryParameters, BlockBuilder bb) { - if (!queryParameters?.parameters) { - return - } - queryParameters.parameters.findAll(this.&allowedQueryParameter). - each { QueryParameter param -> - bb.addLine(".queryParam(\"$param.name\", \"${resolveParamValue(param).toString()}\")") - } - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) { - if (value.isByte()) { - return "assertThat(response.readEntity(byte[].class)).isEqualTo(" + - readBytesFromFileString(value, CommunicationType.RESPONSE) + ")" - } - return getResponseBodyPropertyComparisonString(property, value.asString()) - } - - protected void appendMethodAndBody(BlockBuilder bb) { - String method = request.method.serverValue.toString().toLowerCase() - if (request.body) { - String contentType = - getHeader('Content-Type') ?: getRequestContentType().mimeType - Object body = request.body.serverValue - String value - if (body instanceof ExecutionProperty) { - value = body.toString() - } - else if (body instanceof FromFileProperty) { - FromFileProperty fileProperty = (FromFileProperty) body - value = fileProperty.isByte() ? - readBytesFromFileString(fileProperty, CommunicationType.REQUEST) : - readStringFromFileString(fileProperty, CommunicationType.REQUEST) - } - else { - value = "\"${getBodyAsString()}\"" - } - bb.addLine(".method(\"${method.toUpperCase()}\", entity(${value}, \"$contentType\"))") - } - else { - bb.addLine(".method(\"${method.toUpperCase()}\")") - } - } - - protected appendHeaders(BlockBuilder bb) { - request.headers?.executeForEachHeader { Header header -> - if (headerOfAbsentType(header)) { - return - } - if (header.name == 'Content-Type' || header.name == 'Accept') { - return - } - bb.addLine(".header(\"${header.name}\", ${quotedAndEscaped(header.serverValue as String)})") - } - } - - protected appendCookies(BlockBuilder bb) { - request.cookies?.executeForEachCookie { Cookie cookie -> - if (cookieOfAbsentType(cookie)) { - return - } - - bb.addLine(".cookie(\"${cookie.key}\", ${quotedAndEscaped(cookie.serverValue as String)})") - } - } - - protected void appendRequestWithRequiredResponseContentType(BlockBuilder bb) { - String acceptHeader = getHeader("Accept") - if (acceptHeader) { - bb.addLine(".request(\"$acceptHeader\")") - } - else { - bb.addLine(".request()") - } - } - - @Override - protected void validateResponseCodeBlock(BlockBuilder bb) { - bb.addLine("assertThat(response.getStatus()).isEqualTo($response.status.serverValue);") - } - - @Override - protected void validateResponseHeadersBlock(BlockBuilder bb) { - response.headers?.executeForEachHeader { Header header -> - processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ? - header.serverValue : - MapConverter.getTestSideValues(header.serverValue)) - } - } - - @Override - protected void validateResponseCookiesBlock(BlockBuilder bb) { - response.cookies?.executeForEachCookie { Cookie cookie -> - processCookieElement(bb, cookie.key, cookie.serverValue instanceof NotToEscapePattern ? - cookie.serverValue : - MapConverter.getTestSideValues(cookie.serverValue)) - } - } - - protected String getHeader(String name) { - return request.headers?.entries?.find { it.name == name }?.serverValue - } - - @Override - protected String getResponseAsString() { - return 'responseAsString' - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) { - if (value instanceof NotToEscapePattern) { - blockBuilder. - addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(((NotToEscapePattern) value).serverValue)}") - } - else { - // fallback - processHeaderElement(blockBuilder, property, value.toString()) - } - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) { - blockBuilder. - addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(value)}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) { - blockBuilder. - addLine("assertThat(response.getHeaderString(\"$property\")).isEqualTo(${value});") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) { - blockBuilder. - addLine("assertThat(response.getHeaderString(\"$property\")).${createHeaderComparison(pattern)}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder. - addLine("${exec.insertValue("response.getHeaderString(\"$property\")")};") - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) { - blockBuilder. - addLine("assertThat(response.getCookies().get(\"$key\")).isNotNull();") - blockBuilder. - addLine("assertThat(response.getCookies().get(\"$key\").getValue()).${createCookieComparison(pattern)}") - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) { - blockBuilder. - addLine("assertThat(response.getCookies().get(\"$key\")).isNotNull();") - blockBuilder. - addLine("assertThat(response.getCookies().get(\"$key\").getValue()).${createCookieComparison(value)}") - } - -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientSpockMethodRequestProcessingBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientSpockMethodRequestProcessingBodyBuilder.groovy deleted file mode 100644 index 8e224071f7..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsClientSpockMethodRequestProcessingBodyBuilder.groovy +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import java.util.regex.Pattern - -import groovy.transform.PackageScope -import groovy.transform.TypeChecked - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.Cookie -import org.springframework.cloud.contract.spec.internal.DslProperty -import org.springframework.cloud.contract.spec.internal.ExecutionProperty -import org.springframework.cloud.contract.spec.internal.FromFileProperty -import org.springframework.cloud.contract.spec.internal.Header -import org.springframework.cloud.contract.spec.internal.NotToEscapePattern -import org.springframework.cloud.contract.spec.internal.QueryParameter -import org.springframework.cloud.contract.spec.internal.QueryParameters -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.util.MapConverter - -/** - * Knows how to build a Spock test method for JaxRs. - * - * Do not change to {@code @CompileStatic} since it's using double dispatch. - * - * @author Olga Maciaszek-Sharma, codearte.io - * - * @since 1.0.0 - */ -@PackageScope -@TypeChecked -class JaxRsClientSpockMethodRequestProcessingBodyBuilder extends SpockMethodRequestProcessingBodyBuilder { - - JaxRsClientSpockMethodRequestProcessingBodyBuilder(Contract stubDefinition, - ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(stubDefinition, configProperties, classDataForMethod) - } - - @Override - protected void given(BlockBuilder bb) {} - - @Override - protected void givenBlock(BlockBuilder bb) { - } - - @Override - protected void when(BlockBuilder bb) { - bb.addLine("def response = webTarget") - bb.indent() - - appendUrlPathAndQueryParameters(bb) - appendRequestWithRequiredResponseContentType(bb) - appendHeaders(bb) - appendCookies(bb) - appendMethodAndBody(bb) - - bb.unindent() - - bb.addEmptyLine() - if (expectsResponseBody()) { - bb.addLine("String responseAsString = response.readEntity(String)") - } - } - - protected void appendRequestWithRequiredResponseContentType(BlockBuilder bb) { - String acceptHeader = getHeader("Accept") - if (acceptHeader) { - bb.addLine(".request('$acceptHeader')") - } - else { - bb.addLine(".request()") - } - } - - protected void appendUrlPathAndQueryParameters(BlockBuilder bb) { - if (request.url) { - bb.addLine(".path(${concreteUrl(request.url)})") - appendQueryParams(request.url.queryParameters, bb) - } - else if (request.urlPath) { - bb.addLine(".path(${concreteUrl(request.urlPath)})") - appendQueryParams(request.urlPath.queryParameters, bb) - } - } - - protected String concreteUrl(DslProperty url) { - Object testSideUrl = MapConverter.getTestSideValues(url) - if (!(testSideUrl instanceof ExecutionProperty)) { - return "'" + testSideUrl.toString() + "'" - } - return testSideUrl.toString() - } - - private void appendQueryParams(QueryParameters queryParameters, BlockBuilder bb) { - if (!queryParameters?.parameters) { - return - } - queryParameters.parameters.findAll(this.&allowedQueryParameter). - each { QueryParameter param -> - bb.addLine(".queryParam('$param.name', '${resolveParamValue(param).toString()}')") - } - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) { - if (value.isByte()) { - return "response.readEntity(byte[]) == " + - readBytesFromFileString(value, CommunicationType.RESPONSE) - } - return getResponseBodyPropertyComparisonString(property, value.asString()) - } - - protected void appendMethodAndBody(BlockBuilder bb) { - String method = request.method.serverValue.toString().toLowerCase() - if (request.body) { - String contentType = - getHeader('Content-Type') ?: getRequestContentType().mimeType - Object body = request.body.serverValue - String value - if (body instanceof ExecutionProperty) { - value = body.toString() - } - else if (body instanceof FromFileProperty) { - FromFileProperty fileProperty = (FromFileProperty) body - value = fileProperty.isByte() ? - readBytesFromFileString(fileProperty, CommunicationType.REQUEST) : - readStringFromFileString(fileProperty, CommunicationType.REQUEST) - } - else { - value = "'${bodyAsString}'" - } - bb.addLine(".method('${method.toUpperCase()}', entity(${value}, '$contentType'))") - } - else { - bb.addLine(".method('${method.toUpperCase()}')") - } - } - - protected appendHeaders(BlockBuilder bb) { - request.headers?.executeForEachHeader { Header header -> - if (headerOfAbsentType(header)) { - return - } - if (header.name == 'Content-Type' || header.name == 'Accept') { - return - } // Particular headers are set via 'request' / 'entity' methods - bb.addLine(".header('${header.name}', '${header.serverValue}')") - } - } - - protected appendCookies(BlockBuilder bb) { - request.cookies?.executeForEachCookie { Cookie cookie -> - if (cookieOfAbsentType(cookie)) { - return - } - - bb.addLine(".cookie('${cookie.key}', '${cookie.serverValue}')") - } - } - - protected String getHeader(String name) { - return request.headers?.entries?.find { it.name == name }?.serverValue - } - - @Override - protected void validateResponseCodeBlock(BlockBuilder bb) { - bb.addLine("response.status == $response.status.serverValue") - } - - @Override - protected void validateResponseHeadersBlock(BlockBuilder bb) { - response.headers?.executeForEachHeader { Header header -> - processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ? - header.serverValue : - MapConverter.getTestSideValues(header.serverValue)) - } - } - - @Override - protected void validateResponseCookiesBlock(BlockBuilder bb) { - response.cookies?.executeForEachCookie { Cookie cookie -> - processCookieElement(bb, cookie.key, cookie.serverValue instanceof NotToEscapePattern ? - cookie.serverValue : - MapConverter.getTestSideValues(cookie.serverValue)) - } - } - - @Override - protected String getResponseAsString() { - return 'responseAsString' - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) { - if (value instanceof NotToEscapePattern) { - blockBuilder. - addLine("response.getHeaderString('$property') ${convertHeaderComparison(((NotToEscapePattern) value).serverValue)}") - } - else { - // fallback - processHeaderElement(blockBuilder, property, value.toString()) - } - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder. - addLine("${exec.insertValue("response.getHeaderString(\'$property\')")}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) { - blockBuilder. - addLine("response.getHeaderString('$property') ${convertHeaderComparison(value)}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) { - blockBuilder.addLine("response.getHeaderString('$property') == ${value}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern value) { - blockBuilder. - addLine("response.getHeaderString('$property') ${convertHeaderComparison(value)}") - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) { - blockBuilder.addLine("response.getCookies().get('$key') != null") - blockBuilder. - addLine("response.getCookies().get('$key').getValue() ${convertCookieComparison(pattern)}") - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) { - blockBuilder.addLine("response.getCookies().get('$key') != null") - blockBuilder. - addLine("response.getCookies().get('$key').getValue() ${convertCookieComparison(value)}") - } - - @Override - protected String postProcessJsonPathCall(String jsonPath) { - if (templateProcessor.containsTemplateEntry(jsonPath)) { - return jsonPath - } - return jsonPath.replace('$', '\\$') - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsGiven.java new file mode 100644 index 0000000000..9fd0eca096 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsGiven.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JaxRsGiven implements Given, JaxRsAcceptor { + + private final GeneratedClassMetaData generatedClassMetaData; + + JaxRsGiven(GeneratedClassMetaData metaData) { + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return acceptType(this.generatedClassMetaData, metadata); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsImports.java new file mode 100644 index 0000000000..e0e43cf648 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsImports.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestMode; + +class JaxRsImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "javax.ws.rs.client.Entity", + "javax.ws.rs.core.Response" }; + + JaxRsImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestMode() == TestMode.JAXRSCLIENT; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestCookiesWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestCookiesWhen.java new file mode 100644 index 0000000000..75f002a330 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestCookiesWhen.java @@ -0,0 +1,81 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Iterator; +import java.util.Set; + +import org.springframework.cloud.contract.spec.internal.Cookie; +import org.springframework.cloud.contract.spec.internal.MatchingStrategy; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JaxRsRequestCookiesWhen implements When { + + private final BlockBuilder blockBuilder; + + private final BodyParser bodyParser; + + JaxRsRequestCookiesWhen(BlockBuilder blockBuilder, BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.bodyParser = bodyParser; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + appendCookies(metadata.getContract().getRequest()); + return this; + } + + private void appendCookies(Request request) { + Iterator iterator = request.getCookies().getEntries().stream() + .filter(cookie -> !cookieOfAbsentType(cookie)).iterator(); + while (iterator.hasNext()) { + Cookie cookie = iterator.next(); + String value = ".cookie(" + this.bodyParser.quotedShortText(cookie.getKey()) + + ", " + this.bodyParser.quotedShortText(cookie.getServerValue()) + + ")"; + if (iterator.hasNext()) { + this.blockBuilder.addLine(value); + } + else { + this.blockBuilder.addIndented(value); + } + } + } + + private boolean cookieOfAbsentType(Cookie cookie) { + return cookie.getServerValue() instanceof MatchingStrategy + && ((MatchingStrategy) cookie.getServerValue()) + .getType() == MatchingStrategy.Type.ABSENT; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.getContract().getRequest().getCookies() != null && !metadata + .getContract().getRequest().getCookies().getEntries().isEmpty() + && !hasOnlyAbsentCookies(metadata); + } + + private boolean hasOnlyAbsentCookies(SingleContractMetadata metadata) { + Set entries = metadata.getContract().getRequest().getCookies() + .getEntries(); + long filteredOut = entries.stream().filter(this::cookieOfAbsentType).count(); + return filteredOut == entries.size(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestHeadersWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestHeadersWhen.java new file mode 100644 index 0000000000..a0fef14dbd --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestHeadersWhen.java @@ -0,0 +1,89 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Iterator; +import java.util.Set; + +import org.springframework.cloud.contract.spec.internal.Header; +import org.springframework.cloud.contract.spec.internal.MatchingStrategy; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JaxRsRequestHeadersWhen implements When { + + private final BlockBuilder blockBuilder; + + private final BodyParser bodyParser; + + JaxRsRequestHeadersWhen(BlockBuilder blockBuilder, BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.bodyParser = bodyParser; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + appendHeaders(metadata.getContract().getRequest()); + return this; + } + + private void appendHeaders(Request request) { + Iterator
iterator = request.getHeaders().getEntries().stream() + .filter(header -> !headerToIgnore(header)).iterator(); + while (iterator.hasNext()) { + Header header = iterator.next(); + String text = ".header(\"" + header.getName() + "\", " + + this.bodyParser.quotedLongText(header.getServerValue()) + ")"; + if (iterator.hasNext()) { + this.blockBuilder.addLine(text); + } + else { + this.blockBuilder.addIndented(text); + } + } + } + + private boolean headerToIgnore(Header header) { + return contentTypeOrAccept(header) || headerOfAbsentType(header); + } + + private boolean contentTypeOrAccept(Header header) { + return "Content-Type".equalsIgnoreCase(header.getName()) + || "Accept".equalsIgnoreCase(header.getName()); + } + + private boolean headerOfAbsentType(Header header) { + return header.getServerValue() instanceof MatchingStrategy + && ((MatchingStrategy) header.getServerValue()) + .getType() == MatchingStrategy.Type.ABSENT; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.getContract().getRequest().getHeaders() != null && !metadata + .getContract().getRequest().getHeaders().getEntries().isEmpty() + && !hasHeaderOnlyContentTypeOrAccept(metadata); + } + + private boolean hasHeaderOnlyContentTypeOrAccept(SingleContractMetadata metadata) { + Set
entries = metadata.getContract().getRequest().getHeaders() + .getEntries(); + long filteredOut = entries.stream().filter(this::headerToIgnore).count(); + return filteredOut == entries.size(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestInvokerWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestInvokerWhen.java new file mode 100644 index 0000000000..d052016a3e --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestInvokerWhen.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JaxRsRequestInvokerWhen implements When, JaxRsBodyParser { + + private final BlockBuilder blockBuilder; + + JaxRsRequestInvokerWhen(BlockBuilder blockBuilder) { + this.blockBuilder = blockBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder.addIndented(".invoke()").addEndingIfNotPresent(); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return true; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestMethodWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestMethodWhen.java new file mode 100644 index 0000000000..03260b698a --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestMethodWhen.java @@ -0,0 +1,88 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.spec.internal.FromFileProperty; +import org.springframework.cloud.contract.spec.internal.Header; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.ContentType; +import org.springframework.util.StringUtils; + +class JaxRsRequestMethodWhen implements When, JaxRsBodyParser { + + private final BlockBuilder blockBuilder; + + private final BodyReader bodyReader; + + JaxRsRequestMethodWhen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.bodyReader = new BodyReader(metaData); + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + appendMethodAndBody(metadata); + return this; + } + + void appendMethodAndBody(SingleContractMetadata metadata) { + Request request = metadata.getContract().getRequest(); + ContentType type = metadata.getInputTestContentType(); + String method = request.getMethod().getServerValue().toString().toLowerCase(); + if (request.getBody() != null) { + String contentType = type.getMimeType(); + contentType = StringUtils.hasText(contentType) ? contentType + : getContentType(request); + Object body = request.getBody().getServerValue(); + String value; + if (body instanceof ExecutionProperty) { + value = body.toString(); + } + else if (body instanceof FromFileProperty) { + FromFileProperty fileProperty = (FromFileProperty) body; + value = fileProperty.isByte() + ? this.bodyReader.readBytesFromFileString(metadata, fileProperty, + CommunicationType.REQUEST) + : this.bodyReader.readStringFromFileString(metadata, fileProperty, + CommunicationType.REQUEST); + } + else { + value = "\"" + requestBodyAsString(metadata) + "\""; + } + this.blockBuilder.addIndented(".build(\"" + method.toUpperCase() + + "\", entity(" + value + ", \"" + contentType + "\"))"); + } + else { + this.blockBuilder.addIndented(".build(\"" + method.toUpperCase() + "\")"); + } + } + + private String getContentType(Request request) { + Header contentType = request.getHeaders().getEntries().stream() + .filter(header -> "Content-Type".equalsIgnoreCase(header.getName())) + .findFirst().orElse(null); + return contentType != null ? contentType.getServerValue().toString() : ""; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return true; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestWhen.java new file mode 100644 index 0000000000..831b276b37 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsRequestWhen.java @@ -0,0 +1,68 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.Header; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.util.StringUtils; + +class JaxRsRequestWhen implements When, JaxRsAcceptor, QueryParamsResolver { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + JaxRsRequestWhen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + appendRequestWithRequiredResponseContentType(metadata.getContract().getRequest()); + return this; + } + + void appendRequestWithRequiredResponseContentType(Request request) { + String acceptHeader = getHeader(request, "Accept"); + if (StringUtils.hasText(acceptHeader)) { + this.blockBuilder.addIndented(".request(\"" + acceptHeader + "\")"); + } + else { + this.blockBuilder.addIndented(".request()"); + } + } + + private String getHeader(Request request, String name) { + if (request.getHeaders() == null || request.getHeaders().getEntries() == null) { + return ""; + } + Header foundHeader = request.getHeaders().getEntries().stream() + .filter(header -> name.equals(header.getName())).findFirst().orElse(null); + if (foundHeader == null) { + return ""; + } + return foundHeader.getServerValue().toString(); + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return acceptType(this.generatedClassMetaData, metadata); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsResponseCookiesThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsResponseCookiesThen.java new file mode 100644 index 0000000000..eaa12a6a91 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsResponseCookiesThen.java @@ -0,0 +1,73 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.Response; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JaxRsResponseCookiesThen implements Then, MockMvcAcceptor, CookieElementProcessor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final ComparisonBuilder comparisonBuilder; + + private final BodyParser bodyParser; + + JaxRsResponseCookiesThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData, + ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.comparisonBuilder = comparisonBuilder; + this.bodyParser = comparisonBuilder.bodyParser(); + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + processCookies(metadata); + return this; + } + + @Override + public ComparisonBuilder comparisonBuilder() { + return this.comparisonBuilder; + } + + @Override + public BlockBuilder blockBuilder() { + return this.blockBuilder; + } + + @Override + public String cookieKey(String key) { + return "response.getCookies().get(" + this.bodyParser.quotedShortText(key) + ")"; + } + + @Override + public String cookieValue(String key) { + return cookieKey(key) + ".getValue()"; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Response response = metadata.getContract().getResponse(); + return response.getCookies() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsResponseHeadersThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsResponseHeadersThen.java new file mode 100644 index 0000000000..07e69ce52a --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsResponseHeadersThen.java @@ -0,0 +1,96 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Iterator; + +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.spec.internal.Header; +import org.springframework.cloud.contract.spec.internal.Headers; +import org.springframework.cloud.contract.spec.internal.NotToEscapePattern; +import org.springframework.cloud.contract.spec.internal.Response; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +class JaxRsResponseHeadersThen implements Then { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final ComparisonBuilder comparisonBuilder; + + JaxRsResponseHeadersThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData, + ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + this.comparisonBuilder = comparisonBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + validateResponseHeadersBlock(metadata); + return this; + } + + private void validateResponseHeadersBlock(SingleContractMetadata metadata) { + Response response = metadata.getContract().getResponse(); + Headers headers = response.getHeaders(); + Iterator
iterator = headers.getEntries().iterator(); + while (iterator.hasNext()) { + Header header = iterator.next(); + String text = processHeaderElement(header.getName(), + header.getServerValue() instanceof NotToEscapePattern + ? header.getServerValue() + : MapConverter.getTestSideValues(header.getServerValue())); + if (iterator.hasNext()) { + this.blockBuilder.addLineWithEnding(text); + } + else { + this.blockBuilder.addIndented(text); + } + } + } + + private String processHeaderElement(String property, Object value) { + if (value instanceof NotToEscapePattern) { + return this.comparisonBuilder + .assertThat("response.getHeaderString(\"" + property + "\")") + + this.comparisonBuilder.createComparison( + ((NotToEscapePattern) value).getServerValue()); + } + else if (value instanceof Number) { + return this.comparisonBuilder + .assertThat("response.getHeaderString(\"" + property + "\")", value); + } + else if (value instanceof ExecutionProperty) { + return ((ExecutionProperty) value) + .insertValue("response.getHeaderString(\"" + property + "\")"); + } + else { + return this.comparisonBuilder + .assertThat("response.getHeaderString(\"" + property + "\")") + + this.comparisonBuilder.createComparison(value); + } + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.getContract().getResponse().getHeaders() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsStaticImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsStaticImports.java new file mode 100644 index 0000000000..717c459f21 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsStaticImports.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestMode; + +class JaxRsStaticImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "javax.ws.rs.client.Entity.*" }; + + JaxRsStaticImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestMode() == TestMode.JAXRSCLIENT; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsStatusCodeThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsStatusCodeThen.java new file mode 100644 index 0000000000..f990f2e85a --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsStatusCodeThen.java @@ -0,0 +1,48 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.Response; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JaxRsStatusCodeThen implements Then { + + private final BlockBuilder blockBuilder; + + private final ComparisonBuilder comparisonBuilder; + + JaxRsStatusCodeThen(BlockBuilder blockBuilder, ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.comparisonBuilder = comparisonBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + Response response = metadata.getContract().getResponse(); + this.blockBuilder + .addIndented(this.comparisonBuilder.assertThat("response.getStatus()", + response.getStatus().getServerValue())) + .addEndingIfNotPresent(); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return true; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsThen.java new file mode 100644 index 0000000000..a613ddf174 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsThen.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JaxRsThen implements Then, BodyMethodVisitor, JaxRsAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final List thens = new LinkedList<>(); + + JaxRsThen(BlockBuilder blockBuilder, GeneratedClassMetaData generatedClassMetaData, + BodyParser bodyParser, ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.thens.addAll(Arrays.asList( + new JaxRsStatusCodeThen(this.blockBuilder, comparisonBuilder), + new JaxRsResponseHeadersThen(this.blockBuilder, generatedClassMetaData, + comparisonBuilder), + new JaxRsResponseCookiesThen(this.blockBuilder, generatedClassMetaData, + comparisonBuilder), + new GenericHttpBodyThen(this.blockBuilder, generatedClassMetaData, + bodyParser, comparisonBuilder))); + } + + @Override + public MethodVisitor apply(SingleContractMetadata singleContractMetadata) { + startBodyBlock(this.blockBuilder, "then:"); + bodyBlock(this.blockBuilder, this.thens, singleContractMetadata); + return this; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return acceptType(this.generatedClassMetaData, singleContractMetadata); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsUrlPathWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsUrlPathWhen.java new file mode 100644 index 0000000000..7159680c28 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsUrlPathWhen.java @@ -0,0 +1,119 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Iterator; + +import org.springframework.cloud.contract.spec.internal.DslProperty; +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.spec.internal.MatchingStrategy; +import org.springframework.cloud.contract.spec.internal.QueryParameter; +import org.springframework.cloud.contract.spec.internal.QueryParameters; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +class JaxRsUrlPathWhen implements When, JaxRsAcceptor, QueryParamsResolver { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + JaxRsUrlPathWhen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + appendUrlPathAndQueryParameters(metadata.getContract().getRequest()); + return this; + } + + private void appendUrlPathAndQueryParameters(Request request) { + if (request.getUrl() != null) { + this.blockBuilder.addIndented(".path(" + concreteUrl(request.getUrl()) + ")"); + appendQueryParams(request.getUrl().getQueryParameters()); + } + else if (request.getUrlPath() != null) { + this.blockBuilder + .addIndented(".path(" + concreteUrl(request.getUrlPath()) + ")"); + appendQueryParams(request.getUrlPath().getQueryParameters()); + } + } + + private String concreteUrl(DslProperty url) { + Object testSideUrl = MapConverter.getTestSideValues(url); + if (!(testSideUrl instanceof ExecutionProperty)) { + return '"' + testSideUrl.toString() + '"'; + } + return testSideUrl.toString(); + } + + private void appendQueryParams(QueryParameters queryParameters) { + if (queryParameters == null || queryParameters.getParameters().isEmpty()) { + return; + } + this.blockBuilder.addEmptyLine(); + Iterator iterator = queryParameters.getParameters().stream() + .filter(this::allowedQueryParameter).iterator(); + while (iterator.hasNext()) { + QueryParameter param = iterator.next(); + String text = ".queryParam(\"" + param.getName() + "\", \"" + + resolveParamValue(param) + "\")"; + if (iterator.hasNext()) { + this.blockBuilder.addLine(text); + } + else { + this.blockBuilder.addIndented(text); + } + } + } + + /** + * @return {@code true} if the query parameter is allowed + */ + private boolean allowedQueryParameter(QueryParameter param) { + return allowedQueryParameter(param.getServerValue()); + } + + /** + * @return {@code true} if the query parameter is allowed + */ + private boolean allowedQueryParameter(MatchingStrategy matchingStrategy) { + return matchingStrategy.getType() != MatchingStrategy.Type.ABSENT; + } + + /** + * @return {@code true} if the query parameter is allowed + */ + private boolean allowedQueryParameter(Object o) { + if (o instanceof QueryParameter) { + return allowedQueryParameter((QueryParameter) o); + } + else if (o instanceof MatchingStrategy) { + return allowedQueryParameter((MatchingStrategy) o); + } + return true; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return acceptType(this.generatedClassMetaData, metadata); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsWhen.java new file mode 100644 index 0000000000..839c91567e --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JaxRsWhen.java @@ -0,0 +1,74 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JaxRsWhen implements When, BodyMethodVisitor, JaxRsAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final JaxRsBodyParser bodyParser; + + private final List whens = new LinkedList<>(); + + JaxRsWhen(BlockBuilder blockBuilder, GeneratedClassMetaData generatedClassMetaData, + JaxRsBodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.bodyParser = bodyParser; + this.whens.addAll(Arrays.asList( + new JaxRsUrlPathWhen(this.blockBuilder, this.generatedClassMetaData), + new JaxRsRequestWhen(this.blockBuilder, this.generatedClassMetaData), + new JaxRsRequestHeadersWhen(this.blockBuilder, bodyParser), + new JaxRsRequestCookiesWhen(this.blockBuilder, bodyParser), + new JaxRsRequestMethodWhen(this.blockBuilder, + this.generatedClassMetaData), + new JaxRsRequestInvokerWhen(this.blockBuilder))); + } + + @Override + public MethodVisitor apply(SingleContractMetadata singleContractMetadata) { + startBodyBlock(this.blockBuilder, "when:"); + this.blockBuilder.addIndented("Response response = webTarget"); + this.blockBuilder.indent(); + indentedBodyBlock(this.blockBuilder, this.whens, singleContractMetadata); + this.blockBuilder.addEmptyLine().endBlock(); + if (expectsResponseBody(singleContractMetadata)) { + this.blockBuilder.addLineWithEnding( + "String responseAsString = " + this.bodyParser.readEntity()); + } + this.blockBuilder.endBlock(); + return this; + } + + private boolean expectsResponseBody(SingleContractMetadata metadata) { + return metadata.getContract().getResponse().getBody() != null; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return acceptType(this.generatedClassMetaData, singleContractMetadata); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonBodyVerificationBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonBodyVerificationBuilder.groovy deleted file mode 100644 index f316a7267b..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonBodyVerificationBuilder.groovy +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import com.jayway.jsonpath.DocumentContext -import com.jayway.jsonpath.JsonPath -import com.jayway.jsonpath.PathNotFoundException -import groovy.json.JsonOutput -import groovy.transform.CompileDynamic -import groovy.transform.CompileStatic -import groovy.transform.PackageScope -import org.apache.commons.beanutils.PropertyUtilsBean - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.ContractTemplate -import org.springframework.cloud.contract.spec.internal.BodyMatcher -import org.springframework.cloud.contract.spec.internal.BodyMatchers -import org.springframework.cloud.contract.spec.internal.ExecutionProperty -import org.springframework.cloud.contract.spec.internal.MatchingType -import org.springframework.cloud.contract.spec.internal.RegexProperty -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.template.TemplateProcessor -import org.springframework.cloud.contract.verifier.util.JsonPaths -import org.springframework.cloud.contract.verifier.util.JsonToJsonPathsConverter -import org.springframework.cloud.contract.verifier.util.MapConverter - -/** - * @author Marcin Grzejszczak - * @author Olga Maciaszek-Sharma - * @since 2.1.0 - */ -@PackageScope -@CompileStatic -class JsonBodyVerificationBuilder implements BodyMethodGeneration, ClassVerifier { - - private static final String FROM_REQUEST_PREFIX = 'request.' - private static final String FROM_REQUEST_BODY = 'escapejsonbody' - private static final String FROM_REQUEST_PATH = 'path' - - private final ContractVerifierConfigProperties configProperties - private final TemplateProcessor templateProcessor - private final ContractTemplate contractTemplate - private final Contract contract - private final Optional lineSuffix - private final Closure postProcessJsonPathCall - - // FIXME - // Passing way more arguments here than I would like to, but since we are planning a major - // refactoring of this module for Hoxton release, leaving it this way for now - JsonBodyVerificationBuilder(ContractVerifierConfigProperties configProperties, - TemplateProcessor templateProcessor, - ContractTemplate contractTemplate, - Contract contract, - Optional lineSuffix, - Closure postProcessJsonPathCall) { - this.configProperties = configProperties - this.templateProcessor = templateProcessor - this.contractTemplate = contractTemplate - this.contract = contract - this.lineSuffix = lineSuffix - this.postProcessJsonPathCall = postProcessJsonPathCall - } - - Object addJsonResponseBodyCheck(BlockBuilder bb, Object convertedResponseBody, - BodyMatchers bodyMatchers, - String responseString, - boolean shouldCommentOutBDDBlocks) { - appendJsonPath(bb, responseString) - DocumentContext parsedRequestBody - boolean dontParseStrings = convertedResponseBody instanceof Map - Closure parsingClosure = dontParseStrings ? Closure.IDENTITY : MapConverter.JSON_PARSING_CLOSURE - if (contract.request?.body) { - def testSideRequestBody = MapConverter - .getTestSideValues(contract.request.body, parsingClosure) - parsedRequestBody = JsonPath.parse(testSideRequestBody) - if (convertedResponseBody instanceof String && ! - textContainsJsonPathTemplate(convertedResponseBody)) { - convertedResponseBody = templateProcessor - .transform(contract.request, convertedResponseBody.toString()) - } - } - Object copiedBody = cloneBody(convertedResponseBody) - convertedResponseBody = JsonToJsonPathsConverter - .removeMatchingJsonPaths(convertedResponseBody, bodyMatchers) - // remove quotes from fromRequest objects before picking json paths - TestSideRequestTemplateModel templateModel = contract.request?.body ? - TestSideRequestTemplateModel.from(contract.request) : null - convertedResponseBody = MapConverter.transformValues(convertedResponseBody, - returnReferencedEntries(templateModel), parsingClosure) - JsonPaths jsonPaths = new JsonToJsonPathsConverter(configProperties). - transformToJsonPathWithTestsSideValues(convertedResponseBody, parsingClosure) - jsonPaths.each { - String method = it.method() - method = processIfTemplateIsPresent(method, parsedRequestBody) - String postProcessedMethod = templateProcessor - .containsJsonPathTemplateEntry(method) ? - method : postProcessJsonPathCall(method) - bb.addLine("assertThatJson(parsedJson)" + postProcessedMethod) - addColonIfRequired(lineSuffix, bb) - } - doBodyMatchingIfPresent(bodyMatchers, bb, copiedBody, shouldCommentOutBDDBlocks) - return convertedResponseBody - } - - protected void checkType(BlockBuilder bb, BodyMatcher it, Object elementFromBody) { - String method = "assertThat((Object) parsedJson.read(${quotedAndEscaped(it.path())})).isInstanceOf(${classToCheck(elementFromBody).name}.class)" - bb.addLine(postProcessJsonPathCall(method)) - addColonIfRequired(lineSuffix, bb) - } - - // we want to make the type more generic (e.g. not ArrayList but List) - @CompileDynamic - protected String sizeCheckMethod(BodyMatcher bodyMatcher, String quotedAndEscaptedPath) { - String prefix = sizeCheckPrefix(bodyMatcher, quotedAndEscaptedPath) - if (bodyMatcher.minTypeOccurrence() != null && bodyMatcher - .maxTypeOccurrence() != null) { - return "${prefix}Between(${bodyMatcher.minTypeOccurrence()}, ${bodyMatcher.maxTypeOccurrence()})" - } - else if (bodyMatcher.minTypeOccurrence() != null) { - return "${prefix}GreaterThanOrEqualTo(${bodyMatcher.minTypeOccurrence()})" - } - else if (bodyMatcher.maxTypeOccurrence() != null) { - return "${prefix}LessThanOrEqualTo(${bodyMatcher.maxTypeOccurrence()})" - } - return prefix - } - - - protected void buildCustomMatchingConditionForEachElement(BlockBuilder bb, String path, String valueAsParam) { - String method = "assertThat((java.lang.Iterable) parsedJson.read(${path}, java.util.Collection.class)).as(${path}).allElementsMatch(${valueAsParam})" - bb.addLine(postProcessJsonPathCall(method)) - } - - @Override - void methodForEqualityCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object copiedBody) { - String path = quotedAndEscaped(bodyMatcher.path()) - Object retrievedValue = value(copiedBody, bodyMatcher) - retrievedValue = retrievedValue instanceof RegexProperty ? - ((RegexProperty) retrievedValue).getPattern().pattern() : retrievedValue - String valueAsParam = retrievedValue instanceof String ? - quotedAndEscaped(retrievedValue.toString()) : objectToString(retrievedValue) - if (arrayRelated(path) && MatchingType.regexRelated(bodyMatcher.matchingType())) { - buildCustomMatchingConditionForEachElement(bb, path, valueAsParam) - } - else { - String comparisonMethod = bodyMatcher. - matchingType() == MatchingType.EQUALITY ? "isEqualTo" : "matches" - String classToCastTo = "${retrievedValue.class.simpleName}.class" - String method = "assertThat(parsedJson.read(${path}, ${classToCastTo})).${comparisonMethod}(${valueAsParam})" - bb.addLine(postProcessJsonPathCall(method)) - } - addColonIfRequired(lineSuffix, bb) - } - - private String objectToString(Object value) { - return value instanceof Long - ? String.valueOf(value).concat("L") : String.valueOf(value) - } - - protected String processIfTemplateIsPresent(String method, DocumentContext parsedRequestBody) { - if (textContainsJsonPathTemplate(method) && contract.request?.body) { - // Unquoting the values of non strings - String jsonPathEntry = templateProcessor.jsonPathFromTemplateEntry(method) - Object object = parsedRequestBody.read(jsonPathEntry) - if (!(object instanceof String)) { - return method - .replace('"' + contractTemplate. - escapedOpeningTemplate(), contractTemplate. - escapedOpeningTemplate()) - .replace(contractTemplate. - escapedClosingTemplate() + '"', contractTemplate. - escapedClosingTemplate()) - .replace('"' + contractTemplate. - openingTemplate(), contractTemplate.openingTemplate()) - .replace(contractTemplate. - closingTemplate() + '"', contractTemplate.closingTemplate()) - } - } - return method - } - - @Override - void methodForCommandExecution(BodyMatcher bodyMatcher, BlockBuilder bb, Object copiedBody) { - String path = quotedAndEscaped(bodyMatcher.path()) - // assert that path exists - retrieveObjectByPath(copiedBody, bodyMatcher.path()) - ExecutionProperty property = bodyMatcher.value() as ExecutionProperty - bb.addLine( - postProcessJsonPathCall(property.insertValue("parsedJson.read(${path})"))) - addColonIfRequired(lineSuffix, bb) - } - - @Override - void methodForNullCheck(BodyMatcher bodyMatcher, BlockBuilder bb) { - String quotedAndEscapedPath = quotedAndEscaped(bodyMatcher.path()) - String method = "assertThat((Object) parsedJson.read(${quotedAndEscapedPath})).isNull()" - bb.addLine(postProcessJsonPathCall(method)) - addColonIfRequired(lineSuffix, bb) - } - - protected boolean arrayRelated(String path) { - return path.contains("[*]") || path.contains("..") - } - - @Override - void methodForTypeCheck(BodyMatcher bodyMatcher, BlockBuilder bb, Object copiedBody) { - Object elementFromBody = value(copiedBody, bodyMatcher) - if (bodyMatcher.minTypeOccurrence() != null || bodyMatcher - .maxTypeOccurrence() != null) { - checkType(bb, bodyMatcher, elementFromBody) - String quotedAndEscaptedPath = quotedAndEscaped(bodyMatcher.path()) - String method = "assertThat((java.lang.Iterable) parsedJson.read(${quotedAndEscaptedPath}, java.util.Collection.class)).${sizeCheckMethod(bodyMatcher, quotedAndEscaptedPath)}" - bb.addLine(postProcessJsonPathCall(method)) - addColonIfRequired(lineSuffix, bb) - } - else { - checkType(bb, bodyMatcher, elementFromBody) - } - } - - - private static Object value(Object body, BodyMatcher bodyMatcher) { - if (bodyMatcher.matchingType() == MatchingType.EQUALITY || !bodyMatcher.value()) { - return retrieveObjectByPath(body, bodyMatcher.path()) - } - return bodyMatcher.value() - } - - private static Object retrieveObjectByPath(Object body, String path) { - try { - return JsonPath.parse(body).read(path) - } - catch (PathNotFoundException e) { - throw new IllegalStateException("Entry for the provided JSON path <${path}> doesn't exist in the body <${JsonOutput.toJson(body)}>", e) - } - } - - @CompileDynamic - private Closure returnReferencedEntries(TestSideRequestTemplateModel templateModel) { - return { entry -> - if (!(entry instanceof String) || !templateModel) { - return entry - } - String entryAsString = (String) entry - if (templateProcessor.containsTemplateEntry(entryAsString) - && - !templateProcessor.containsJsonPathTemplateEntry(entryAsString)) { - // TODO: HANDLEBARS LEAKING VIA request. - String justEntry = entryAsString - contractTemplate. - escapedOpeningTemplate() - - contractTemplate.openingTemplate() - - contractTemplate.escapedClosingTemplate() - - contractTemplate.closingTemplate() - FROM_REQUEST_PREFIX - if (justEntry == FROM_REQUEST_BODY) { - // the body should be transformed by standard mechanism - return contractTemplate. - escapedOpeningTemplate() + FROM_REQUEST_PREFIX + - "escapedBody" + contractTemplate.escapedClosingTemplate() - } - try { - Object result = new PropertyUtilsBean() - .getProperty(templateModel, justEntry) - // Path from the Test model is an object and we'd like to return its String representation - if (justEntry == FROM_REQUEST_PATH) { - return result.toString() - } - return result - } - catch (Exception ignored) { - return entry - } - } - return entry - } - } - - protected boolean textContainsJsonPathTemplate(String method) { - return templateProcessor.containsTemplateEntry(method) && - templateProcessor.containsJsonPathTemplateEntry(method) - } - - /** - * Appends to {@link BlockBuilder} parsing of the JSON Path document - */ - protected void appendJsonPath(BlockBuilder blockBuilder, String json) { - blockBuilder.addLine(("DocumentContext parsedJson = JsonPath.parse($json)")) - addColonIfRequired(lineSuffix, blockBuilder) - } - - private String sizeCheckPrefix(BodyMatcher bodyMatcher, String quotedAndEscaptedPath) { - String description = "as(" + quotedAndEscaptedPath + ")." - String prefix = description + "has" - if (arrayRelated(bodyMatcher.path())) { - prefix = prefix + "Flattened" - } - return prefix + "Size" - } - - private void doBodyMatchingIfPresent(BodyMatchers bodyMatchers, BlockBuilder bb, - Object responseBody, boolean shouldCommentOutBDDBlocks) { - if (bodyMatchers?.hasMatchers()) { - addBodyMatchingBlock(bodyMatchers. - matchers(), bb, responseBody, shouldCommentOutBDDBlocks) - } - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonBodyVerificationBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonBodyVerificationBuilder.java new file mode 100644 index 0000000000..dfaa83f883 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonBodyVerificationBuilder.java @@ -0,0 +1,363 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Map; +import java.util.Optional; +import java.util.function.Function; + +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import com.jayway.jsonpath.PathNotFoundException; +import groovy.json.JsonOutput; +import groovy.lang.Closure; +import org.apache.commons.beanutils.PropertyUtilsBean; + +import org.springframework.cloud.contract.spec.Contract; +import org.springframework.cloud.contract.spec.ContractTemplate; +import org.springframework.cloud.contract.spec.internal.BodyMatcher; +import org.springframework.cloud.contract.spec.internal.BodyMatchers; +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.spec.internal.MatchingType; +import org.springframework.cloud.contract.spec.internal.RegexProperty; +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties; +import org.springframework.cloud.contract.verifier.template.TemplateProcessor; +import org.springframework.cloud.contract.verifier.util.JsonPaths; +import org.springframework.cloud.contract.verifier.util.JsonToJsonPathsConverter; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +/** + * @author Marcin Grzejszczak + * @author Olga Maciaszek-Sharma + * @since 2.1.0 + */ +class JsonBodyVerificationBuilder implements BodyMethodGeneration, ClassVerifier { + + private static final String FROM_REQUEST_PREFIX = "request."; + + private static final String FROM_REQUEST_BODY = "escapejsonbody"; + + private static final String FROM_REQUEST_PATH = "path"; + + private final ContractVerifierConfigProperties configProperties; + + private final TemplateProcessor templateProcessor; + + private final ContractTemplate contractTemplate; + + private final Contract contract; + + private final Optional lineSuffix; + + private final Function postProcessJsonPathCall; + + // FIXME + // Passing way more arguments here than I would like to, but since we are planning a + // major + // refactoring of this module for Hoxton release, leaving it this way for now + JsonBodyVerificationBuilder(ContractVerifierConfigProperties configProperties, + TemplateProcessor templateProcessor, ContractTemplate contractTemplate, + Contract contract, Optional lineSuffix, + Function postProcessJsonPathCall) { + this.configProperties = configProperties; + this.templateProcessor = templateProcessor; + this.contractTemplate = contractTemplate; + this.contract = contract; + this.lineSuffix = lineSuffix; + this.postProcessJsonPathCall = postProcessJsonPathCall; + } + + Object addJsonResponseBodyCheck(BlockBuilder bb, Object convertedResponseBody, + BodyMatchers bodyMatchers, String responseString, + boolean shouldCommentOutBDDBlocks) { + appendJsonPath(bb, responseString); + DocumentContext parsedRequestBody = null; + boolean dontParseStrings = convertedResponseBody instanceof Map; + Closure parsingClosure = dontParseStrings ? Closure.IDENTITY + : MapConverter.JSON_PARSING_CLOSURE; + if (hasRequestBody()) { + Object testSideRequestBody = MapConverter + .getTestSideValues(contract.getRequest().getBody(), parsingClosure); + parsedRequestBody = JsonPath.parse(testSideRequestBody); + if (convertedResponseBody instanceof String + && !textContainsJsonPathTemplate(convertedResponseBody.toString())) { + convertedResponseBody = templateProcessor.transform(contract.getRequest(), + convertedResponseBody.toString()); + } + } + Object copiedBody = cloneBody(convertedResponseBody); + convertedResponseBody = JsonToJsonPathsConverter + .removeMatchingJsonPaths(convertedResponseBody, bodyMatchers); + // remove quotes from fromRequest objects before picking json paths + TestSideRequestTemplateModel templateModel = hasRequestBody() + ? TestSideRequestTemplateModel.from(contract.getRequest()) : null; + convertedResponseBody = MapConverter.transformValues(convertedResponseBody, + returnReferencedEntries(templateModel), parsingClosure); + JsonPaths jsonPaths = new JsonToJsonPathsConverter(configProperties) + .transformToJsonPathWithTestsSideValues(convertedResponseBody, + parsingClosure); + DocumentContext finalParsedRequestBody = parsedRequestBody; + jsonPaths.forEach(it -> { + String method = it.method(); + method = processIfTemplateIsPresent(method, finalParsedRequestBody); + String postProcessedMethod = templateProcessor.containsJsonPathTemplateEntry( + method) ? method : postProcessJsonPathCall.apply(method); + bb.addLine("assertThatJson(parsedJson)" + postProcessedMethod); + addColonIfRequired(lineSuffix, bb); + }); + doBodyMatchingIfPresent(bodyMatchers, bb, copiedBody, shouldCommentOutBDDBlocks); + return convertedResponseBody; + } + + private boolean hasRequestBody() { + return contract.getRequest() != null && contract.getRequest().getBody() != null; + } + + private void checkType(BlockBuilder bb, BodyMatcher it, Object elementFromBody) { + String method = "assertThat((Object) parsedJson.read(" + + quotedAndEscaped(it.path()) + ")).isInstanceOf(" + + classToCheck(elementFromBody).getName() + ".class)"; + bb.addLine(postProcessJsonPathCall.apply(method)); + addColonIfRequired(lineSuffix, bb); + } + + // we want to make the type more generic (e.g. not ArrayList but List) + private String sizeCheckMethod(BodyMatcher bodyMatcher, + String quotedAndEscaptedPath) { + String prefix = sizeCheckPrefix(bodyMatcher, quotedAndEscaptedPath); + if (bodyMatcher.minTypeOccurrence() != null + && bodyMatcher.maxTypeOccurrence() != null) { + return prefix + "Between(" + bodyMatcher.minTypeOccurrence() + ", " + + bodyMatcher.maxTypeOccurrence() + ")"; + } + else if (bodyMatcher.minTypeOccurrence() != null) { + return prefix + "GreaterThanOrEqualTo(" + bodyMatcher.minTypeOccurrence() + + ")"; + } + else if (bodyMatcher.maxTypeOccurrence() != null) { + return prefix + "LessThanOrEqualTo(" + bodyMatcher.maxTypeOccurrence() + ")"; + } + return prefix; + } + + protected void buildCustomMatchingConditionForEachElement(BlockBuilder bb, + String path, String valueAsParam) { + String method = "assertThat((java.lang.Iterable) parsedJson.read(" + path + + ", java.util.Collection.class)).as(" + path + ").allElementsMatch(" + + valueAsParam + ")"; + bb.addLine(postProcessJsonPathCall.apply(method)); + } + + @Override + public void methodForEqualityCheck(BodyMatcher bodyMatcher, BlockBuilder bb, + Object copiedBody) { + String path = quotedAndEscaped(bodyMatcher.path()); + Object retrievedValue = value(copiedBody, bodyMatcher); + retrievedValue = retrievedValue instanceof RegexProperty + ? ((RegexProperty) retrievedValue).getPattern().pattern() + : retrievedValue; + String valueAsParam = retrievedValue instanceof String + ? quotedAndEscaped(retrievedValue.toString()) + : objectToString(retrievedValue); + if (arrayRelated(path) && MatchingType.regexRelated(bodyMatcher.matchingType())) { + buildCustomMatchingConditionForEachElement(bb, path, valueAsParam); + } + else { + String comparisonMethod = bodyMatcher.matchingType() == MatchingType.EQUALITY + ? "isEqualTo" : "matches"; + String classToCastTo = retrievedValue.getClass().getSimpleName() + ".class"; + String method = "assertThat(parsedJson.read(" + path + ", " + classToCastTo + + "))." + comparisonMethod + "(" + valueAsParam + ")"; + bb.addLine(postProcessJsonPathCall.apply(method)); + } + addColonIfRequired(lineSuffix, bb); + } + + private String objectToString(Object value) { + return value instanceof Long ? String.valueOf(value).concat("L") + : String.valueOf(value); + } + + protected String processIfTemplateIsPresent(String method, + DocumentContext parsedRequestBody) { + if (textContainsJsonPathTemplate(method) && hasRequestBody()) { + // Unquoting the values of non strings + String jsonPathEntry = templateProcessor.jsonPathFromTemplateEntry(method); + Object object = parsedRequestBody.read(jsonPathEntry); + if (!(object instanceof String)) { + return method + .replace('"' + contractTemplate.escapedOpeningTemplate(), + contractTemplate.escapedOpeningTemplate()) + .replace(contractTemplate.escapedClosingTemplate() + '"', + contractTemplate.escapedClosingTemplate()) + .replace('"' + contractTemplate.openingTemplate(), + contractTemplate.openingTemplate()) + .replace(contractTemplate.closingTemplate() + '"', + contractTemplate.closingTemplate()); + } + } + return method; + } + + @Override + public void methodForCommandExecution(BodyMatcher bodyMatcher, BlockBuilder bb, + Object copiedBody) { + String path = quotedAndEscaped(bodyMatcher.path()); + // assert that path exists + retrieveObjectByPath(copiedBody, bodyMatcher.path()); + ExecutionProperty property = (ExecutionProperty) bodyMatcher.value(); + bb.addLine(postProcessJsonPathCall + .apply(property.insertValue("parsedJson.read(" + path + ")"))); + addColonIfRequired(lineSuffix, bb); + } + + @Override + public void methodForNullCheck(BodyMatcher bodyMatcher, BlockBuilder bb) { + String quotedAndEscapedPath = quotedAndEscaped(bodyMatcher.path()); + String method = "assertThat((Object) parsedJson.read(" + quotedAndEscapedPath + + ")).isNull()"; + bb.addLine(postProcessJsonPathCall.apply(method)); + addColonIfRequired(lineSuffix, bb); + } + + private boolean arrayRelated(String path) { + return path.contains("[*]") || path.contains(".."); + } + + @Override + public void methodForTypeCheck(BodyMatcher bodyMatcher, BlockBuilder bb, + Object copiedBody) { + Object elementFromBody = value(copiedBody, bodyMatcher); + if (bodyMatcher.minTypeOccurrence() != null + || bodyMatcher.maxTypeOccurrence() != null) { + checkType(bb, bodyMatcher, elementFromBody); + String quotedAndEscaptedPath = quotedAndEscaped(bodyMatcher.path()); + String method = "assertThat((java.lang.Iterable) parsedJson.read(" + + quotedAndEscaptedPath + ", java.util.Collection.class))." + + sizeCheckMethod(bodyMatcher, quotedAndEscaptedPath); + bb.addLine(postProcessJsonPathCall.apply(method)); + addColonIfRequired(lineSuffix, bb); + } + else { + checkType(bb, bodyMatcher, elementFromBody); + } + } + + private static Object value(Object body, BodyMatcher bodyMatcher) { + if (bodyMatcher.matchingType() == MatchingType.EQUALITY + || bodyMatcher.value() == null) { + return retrieveObjectByPath(body, bodyMatcher.path()); + } + return bodyMatcher.value(); + } + + private static Object retrieveObjectByPath(Object body, String path) { + try { + return JsonPath.parse(body).read(path); + } + catch (PathNotFoundException e) { + throw new IllegalStateException("Entry for the provided JSON path <" + path + + "> doesn't exist in the body <" + JsonOutput.toJson(body) + ">", e); + } + } + + private Closure returnReferencedEntries( + TestSideRequestTemplateModel templateModel) { + return MapConverter.fromFunction(entry -> { + if (!(entry instanceof String) || templateModel == null) { + return entry; + } + String entryAsString = (String) entry; + if (this.templateProcessor.containsTemplateEntry(entryAsString) + && !this.templateProcessor + .containsJsonPathTemplateEntry(entryAsString)) { + // TODO: HANDLEBARS LEAKING VIA request. + String justEntry = minus(entryAsString, + contractTemplate.escapedOpeningTemplate()); + justEntry = minus(justEntry, contractTemplate.openingTemplate()); + justEntry = minus(justEntry, contractTemplate.escapedClosingTemplate()); + justEntry = minus(justEntry, contractTemplate.closingTemplate()); + justEntry = minus(justEntry, FROM_REQUEST_PREFIX); + if (FROM_REQUEST_BODY.equalsIgnoreCase(justEntry)) { + // the body should be transformed by standard mechanism + return contractTemplate.escapedOpeningTemplate() + FROM_REQUEST_PREFIX + + "escapedBody" + contractTemplate.escapedClosingTemplate(); + } + try { + Object result = new PropertyUtilsBean().getProperty(templateModel, + justEntry); + // Path from the Test model is an object and we'd like to return its + // String representation + if (FROM_REQUEST_PATH.equals(justEntry)) { + return result.toString(); + } + return result; + } + catch (Exception ignored) { + return entry; + } + } + return entry; + }); + } + + private static String minus(CharSequence self, Object target) { + String s = self.toString(); + String text = target.toString(); + int index = s.indexOf(text); + if (index == -1) { + return s; + } + int end = index + text.length(); + if (s.length() > end) { + return s.substring(0, index) + s.substring(end); + } + return s.substring(0, index); + } + + private boolean textContainsJsonPathTemplate(String method) { + return templateProcessor.containsTemplateEntry(method) + && templateProcessor.containsJsonPathTemplateEntry(method); + } + + /** + * Appends to {@link BlockBuilder} parsing of the JSON Path document + */ + private void appendJsonPath(BlockBuilder blockBuilder, String json) { + blockBuilder.addLine("DocumentContext parsedJson = JsonPath.parse(" + json + ")"); + addColonIfRequired(lineSuffix, blockBuilder); + } + + private String sizeCheckPrefix(BodyMatcher bodyMatcher, String quotedAndEscapedPath) { + String description = "as(" + quotedAndEscapedPath + ")."; + String prefix = description + "has"; + if (arrayRelated(bodyMatcher.path())) { + prefix = prefix + "Flattened"; + } + return prefix + "Size"; + } + + private void doBodyMatchingIfPresent(BodyMatchers bodyMatchers, BlockBuilder bb, + Object responseBody, boolean shouldCommentOutBDDBlocks) { + if (bodyMatchers != null && bodyMatchers.hasMatchers()) { + bb.addEmptyLine(); + addBodyMatchingBlock(bodyMatchers.matchers(), bb, responseBody, + shouldCommentOutBDDBlocks); + } + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonImports.java new file mode 100644 index 0000000000..320cefc624 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonImports.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JsonImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "org.junit.FixMethodOrder", + "org.junit.runners.MethodSorters" }; + + JsonImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(metadata -> metadata.getConvertedContractWithMetadata().stream() + .anyMatch(SingleContractMetadata::isJson)); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonPathImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonPathImports.java new file mode 100644 index 0000000000..4a53853583 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/JsonPathImports.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class JsonPathImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "com.jayway.jsonpath.DocumentContext", + "com.jayway.jsonpath.JsonPath" }; + + JsonPathImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(metadata -> metadata.getConvertedContractWithMetadata().stream() + .anyMatch(SingleContractMetadata::isJson)); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingAssertThatThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingAssertThatThen.java new file mode 100644 index 0000000000..8c87c0ba4b --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingAssertThatThen.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingAssertThatThen implements Then { + + private final BlockBuilder blockBuilder; + + MessagingAssertThatThen(BlockBuilder blockBuilder) { + this.blockBuilder = blockBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder.addLineWithEnding(metadata.getContract().getOutputMessage() + .getAssertThat().getExecutionCommand()); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.getContract().getOutputMessage().getAssertThat() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingAssertThatWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingAssertThatWhen.java new file mode 100644 index 0000000000..452d99e8b8 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingAssertThatWhen.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingAssertThatWhen implements When { + + private final BlockBuilder blockBuilder; + + MessagingAssertThatWhen(BlockBuilder blockBuilder) { + this.blockBuilder = blockBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder.addIndented( + metadata.getContract().getInput().getAssertThat().getExecutionCommand()); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.getContract().getInput().getAssertThat() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyGiven.java new file mode 100644 index 0000000000..ded1834b5d --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyGiven.java @@ -0,0 +1,71 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.FromFileProperty; +import org.springframework.cloud.contract.spec.internal.Input; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.ContentType; + +class MessagingBodyGiven implements Given, MethodVisitor { + + private final BlockBuilder blockBuilder; + + private final BodyReader bodyReader; + + private final BodyParser bodyParser; + + MessagingBodyGiven(BlockBuilder blockBuilder, BodyReader bodyReader, + BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.bodyReader = bodyReader; + this.bodyParser = bodyParser; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + appendBodyGiven(metadata); + return this; + } + + private void appendBodyGiven(SingleContractMetadata metadata) { + ContentType contentType = metadata.getInputTestContentType(); + Input inputMessage = metadata.getContract().getInput(); + Object bodyValue = this.bodyParser.extractServerValueFromBody(contentType, + inputMessage.getMessageBody().getServerValue()); + if (bodyValue instanceof FromFileProperty) { + FromFileProperty fileProperty = (FromFileProperty) bodyValue; + String byteText = fileProperty.isByte() + ? this.bodyReader.readBytesFromFileString(metadata, fileProperty, + CommunicationType.REQUEST) + : this.bodyParser.quotedLongText( + this.bodyReader.readStringFromFileString(metadata, + fileProperty, CommunicationType.REQUEST)); + this.blockBuilder.addIndented(byteText); + } + else { + String text = this.bodyParser.convertToJsonString(bodyValue); + this.blockBuilder.addIndented(this.bodyParser.quotedEscapedLongText(text)); + } + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.getContract().getInput().getMessageBody() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyParser.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyParser.java new file mode 100644 index 0000000000..caa41cecdc --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyParser.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.BodyMatchers; +import org.springframework.cloud.contract.spec.internal.DslProperty; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +interface MessagingBodyParser extends BodyParser { + + default String responseAsString() { + return "contractVerifierObjectMapper.writeValueAsString(response.getPayload())"; + } + + default String byteArrayString() { + return "response.getPayloadAsByteArray()"; + } + + @Override + default DslProperty responseBody(SingleContractMetadata metadata) { + return metadata.getContract().getOutputMessage().getBody(); + } + + @Override + default BodyMatchers responseBodyMatchers(SingleContractMetadata metadata) { + return metadata.getContract().getOutputMessage().getBodyMatchers(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyThen.java new file mode 100644 index 0000000000..004800e1db --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyThen.java @@ -0,0 +1,68 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingBodyThen implements Then, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final ComparisonBuilder comparisonBuilder; + + private final List thens = new LinkedList<>(); + + private final BodyParser bodyParser; + + MessagingBodyThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData, + ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + this.comparisonBuilder = comparisonBuilder; + this.bodyParser = comparisonBuilder.bodyParser(); + this.thens.addAll(Arrays.asList( + new GenericBinaryBodyThen(blockBuilder, metaData, this.bodyParser, + this.comparisonBuilder), + new GenericTextBodyThen(blockBuilder, metaData, this.bodyParser, + this.comparisonBuilder), + new GenericJsonBodyThen(blockBuilder, metaData, this.bodyParser, + this.comparisonBuilder), + new GenericXmlBodyThen(blockBuilder, this.bodyParser))); + } + + @Override + public MethodVisitor apply(SingleContractMetadata singleContractMetadata) { + endBodyBlock(this.blockBuilder); + startBodyBlock(this.blockBuilder, "and:"); + this.thens.stream().filter(then -> then.accept(singleContractMetadata)) + .forEach(then -> then.apply(singleContractMetadata)); + return this; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return singleContractMetadata.isMessaging() + && this.bodyParser.responseBody(singleContractMetadata) != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyWhen.java new file mode 100644 index 0000000000..8a1ce04e4a --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingBodyWhen.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingBodyWhen implements When { + + private final BlockBuilder blockBuilder; + + MessagingBodyWhen(BlockBuilder blockBuilder) { + this.blockBuilder = blockBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder.addIndented("contractVerifierMessaging.send(inputMessage, \"" + + metadata.getContract().getInput().getMessageFrom().getServerValue() + + "\")").addEndingIfNotPresent(); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.getContract().getInput().getMessageFrom() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingFields.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingFields.java new file mode 100644 index 0000000000..9c805cab25 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingFields.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingFields implements Field { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] FIELDS = { + "@Inject ContractVerifierMessaging contractVerifierMessaging", + "@Inject ContractVerifierObjectMapper contractVerifierObjectMapper" }; + + MessagingFields(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Field call() { + Arrays.stream(FIELDS).forEach(this.blockBuilder::addLineWithEnding); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(metadata -> metadata.getConvertedContractWithMetadata().stream() + .anyMatch(SingleContractMetadata::isMessaging)); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingGiven.java new file mode 100644 index 0000000000..970a398a5e --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingGiven.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingGiven implements Given, MethodVisitor, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final List givens = new LinkedList<>(); + + MessagingGiven(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData, BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.givens.addAll(Arrays.asList( + new MessagingBodyGiven(this.blockBuilder, + new BodyReader(this.generatedClassMetaData), bodyParser), + new MessagingHeadersGiven(this.blockBuilder))); + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + startBodyBlock(this.blockBuilder, "given:"); + this.blockBuilder.addIndented( + "ContractVerifierMessage inputMessage = contractVerifierMessaging.create(") + .addEmptyLine().indent(); + this.givens.stream().filter(given -> given.accept(metadata)).forEach(given -> { + given.apply(metadata); + this.blockBuilder.addEmptyLine(); + }); + this.blockBuilder.unindent().unindent().startBlock().addIndented(")") + .addEndingIfNotPresent().addEmptyLine().endBlock(); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.isMessaging() + && metadata.getContract().getInput().getTriggeredBy() == null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingHeadersGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingHeadersGiven.java new file mode 100644 index 0000000000..8b07fb1208 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingHeadersGiven.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.Header; +import org.springframework.cloud.contract.spec.internal.Input; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +class MessagingHeadersGiven implements Given, MethodVisitor { + + private final BlockBuilder blockBuilder; + + MessagingHeadersGiven(BlockBuilder blockBuilder) { + this.blockBuilder = blockBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + Input inputMessage = metadata.getContract().getInput(); + this.blockBuilder.startBlock().addIndented(", headers()").startBlock(); + inputMessage.getMessageHeaders().executeForEachHeader(header -> { + this.blockBuilder.addEmptyLine().addIndented(getHeaderString(header)); + }); + this.blockBuilder.endBlock(); + return this; + } + + private String getHeaderString(Header header) { + return ".header(" + getTestSideValue(header.getName()) + ", " + + getTestSideValue(header.getServerValue()) + ")"; + } + + private String getTestSideValue(Object object) { + return '"' + MapConverter.getTestSideValues(object).toString() + '"'; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.getContract().getInput().getMessageHeaders() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingHeadersThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingHeadersThen.java new file mode 100644 index 0000000000..b98141cd49 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingHeadersThen.java @@ -0,0 +1,108 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.regex.Pattern; + +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.spec.internal.NotToEscapePattern; +import org.springframework.cloud.contract.spec.internal.OutputMessage; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +class MessagingHeadersThen implements Then, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final ComparisonBuilder comparisonBuilder; + + MessagingHeadersThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData, + ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.comparisonBuilder = comparisonBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata singleContractMetadata) { + endBodyBlock(this.blockBuilder); + startBodyBlock(this.blockBuilder, "and:"); + OutputMessage outputMessage = singleContractMetadata.getContract() + .getOutputMessage(); + outputMessage.getHeaders().executeForEachHeader(header -> { + processHeaderElement(header.getName(), + header.getServerValue() instanceof NotToEscapePattern + ? header.getServerValue() + : MapConverter.getTestSideValues(header.getServerValue())); + }); + return this; + } + + private void appendLineWithHeaderNotNull(String property) { + this.blockBuilder.addLineWithEnding(this.comparisonBuilder + .assertThatIsNotNull("response.getHeader(\"" + property + "\")")); + } + + private void processHeaderElement(String property, Object value) { + if (value instanceof Number) { + processHeaderElement(property, (Number) value); + } + else if (value instanceof Pattern) { + processHeaderElement(property, (Pattern) value); + } + else if (value instanceof ExecutionProperty) { + processHeaderElement(property, (ExecutionProperty) value); + } + else { + processHeaderElement(property, value.toString()); + } + } + + private void processHeaderElement(String property, String value) { + appendLineWithHeaderNotNull(property); + this.blockBuilder.addLineWithEnding(this.comparisonBuilder.assertThat( + "response.getHeader(\"" + property + "\").toString()", value)); + } + + private void processHeaderElement(String property, Number value) { + appendLineWithHeaderNotNull(property); + blockBuilder.addLineWithEnding(this.comparisonBuilder + .assertThat("response.getHeader(\"" + property + "\")", value)); + } + + private void processHeaderElement(String property, Pattern pattern) { + appendLineWithHeaderNotNull(property); + blockBuilder.addLineWithEnding(this.comparisonBuilder.assertThat( + "response.getHeader(\"" + property + "\").toString()", pattern)); + } + + private void processHeaderElement(String property, ExecutionProperty exec) { + appendLineWithHeaderNotNull(property); + blockBuilder.addLineWithEnding( + exec.insertValue("response.getHeader(\"" + property + "\").toString()")); + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return singleContractMetadata.isMessaging() && singleContractMetadata + .getContract().getOutputMessage().getHeaders() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingImports.java new file mode 100644 index 0000000000..0a9d2cc063 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingImports.java @@ -0,0 +1,54 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "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" }; + + MessagingImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(metadata -> metadata.getConvertedContractWithMetadata().stream() + .anyMatch(SingleContractMetadata::isMessaging)); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilder.groovy deleted file mode 100644 index 35b2464a06..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilder.groovy +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import groovy.json.JsonOutput -import groovy.transform.PackageScope -import groovy.transform.TypeChecked - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.FromFileProperty -import org.springframework.cloud.contract.spec.internal.Input -import org.springframework.cloud.contract.spec.internal.OutputMessage -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.util.ContentType -import org.springframework.cloud.contract.verifier.util.ContentUtils - -import static org.apache.commons.text.StringEscapeUtils.escapeJava -import static org.springframework.cloud.contract.verifier.util.ContentUtils.evaluateContentType - -/** - * Root class for messaging method building. - * - * Do not change to {@code @CompileStatic} since it's using double dispatch. - * - * @author Olga Maciaszek-Sharma, codearte.io - * @author Tim Ysewyn - * - * @since 1.0.0 - */ -@TypeChecked -@PackageScope -abstract class MessagingMethodBodyBuilder extends MethodBodyBuilder { - - protected final Input inputMessage - protected final OutputMessage outputMessage - - MessagingMethodBodyBuilder(Contract stubDefinition, - ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(configProperties, stubDefinition, classDataForMethod) - this.inputMessage = stubDefinition.input - this.outputMessage = stubDefinition.outputMessage - } - - protected abstract String getInputString(Input request) - - @Override - protected boolean hasGivenSection() { - return !inputMessage.triggeredBy - } - - protected void processInput(BlockBuilder bb) { - - } - - protected void when(BlockBuilder bb) { - bb.addLine(getInputString(inputMessage)) - bb.indent() - - addColonIfRequired(bb) - bb.unindent() - } - - protected void then(BlockBuilder bb) { - validateResponseCodeBlock(bb) - if (inputMessage.assertThat) { - bb.addLine(inputMessage.assertThat.executionCommand) - addColonIfRequired(bb) - } - if (outputMessage) { - validateResponseHeadersBlock(bb) - if (outputMessage.body) { - bb.endBlock() - if (outputMessage.headers) { - bb.addLine(addCommentSignIfRequired('and:')).startBlock() - } - else { - bb.startBlock() - } - validateResponseBodyBlock(bb, outputMessage.bodyMatchers, outputMessage.body.serverValue) - } - if (outputMessage.assertThat) { - bb.addLine(outputMessage.assertThat.executionCommand) - addColonIfRequired(bb) - } - } - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, GString value) { - String gstringValue = ContentUtils. - extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString() - processHeaderElement(blockBuilder, property, gstringValue) - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) { - return null - } - - protected ContentType getResponseContentType() { - return evaluateContentType(outputMessage?.headers, - outputMessage?.body?.serverValue) - } - - protected String getBodyAsString() { - ContentType contentType = contentType() - Object bodyValue = - extractServerValueFromBody(contentType, inputMessage.messageBody.serverValue) - if (bodyValue instanceof FromFileProperty) { - FromFileProperty fileProperty = (FromFileProperty) bodyValue - return fileProperty.isByte() ? - indentBody( - readBytesFromFileString(fileProperty, CommunicationType.REQUEST)) : - indentStringBody( - readStringFromFileString(fileProperty, CommunicationType.REQUEST)) - } - String json = new JsonOutput().toJson(bodyValue) - json = convertUnicodeEscapesIfRequired(json) - return indentStringBody(trimRepeatedQuotes(json)) - } - - protected String indentBody(String text) { - return "\n\t\t\t\t${text}\n" - } - - protected String indentStringBody(String text) { - return indentBody("${quotes()}${escapeJava(text)}${quotes()}") - } - - protected String quotes() { - return "\"" - } - -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingReceiveMessageThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingReceiveMessageThen.java new file mode 100644 index 0000000000..038085f2a3 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingReceiveMessageThen.java @@ -0,0 +1,64 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.spec.internal.OutputMessage; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingReceiveMessageThen implements Then, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final ComparisonBuilder comparisonBuilder; + + MessagingReceiveMessageThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData, + ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.comparisonBuilder = comparisonBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata singleContractMetadata) { + OutputMessage outputMessage = singleContractMetadata.getContract() + .getOutputMessage(); + this.blockBuilder.addLineWithEnding( + "ContractVerifierMessage response = contractVerifierMessaging.receive(" + + sentToValue(outputMessage.getSentTo().getServerValue()) + ")"); + this.blockBuilder.addLineWithEnding( + this.comparisonBuilder.assertThatIsNotNull("response")); + return this; + } + + private String sentToValue(Object sentTo) { + if (sentTo instanceof ExecutionProperty) { + return ((ExecutionProperty) sentTo).getExecutionCommand(); + } + return '"' + sentTo.toString() + '"'; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return singleContractMetadata.isMessaging() && singleContractMetadata + .getContract().getOutputMessage().getSentTo() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingSpockNoMessageThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingSpockNoMessageThen.java new file mode 100644 index 0000000000..5999858b36 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingSpockNoMessageThen.java @@ -0,0 +1,48 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingSpockNoMessageThen implements Then, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + MessagingSpockNoMessageThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata singleContractMetadata) { + this.blockBuilder.addLineWithEnding("noExceptionThrown()"); + return this; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return singleContractMetadata.isMessaging() + && singleContractMetadata.getContract().getOutputMessage() == null + && this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingStaticImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingStaticImports.java new file mode 100644 index 0000000000..f56f255734 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingStaticImports.java @@ -0,0 +1,53 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingStaticImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { + "org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers", + "org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes" }; + + MessagingStaticImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(metadata -> metadata.getConvertedContractWithMetadata().stream() + .anyMatch(SingleContractMetadata::isMessaging)); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingTriggeredByWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingTriggeredByWhen.java new file mode 100644 index 0000000000..2f30696309 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingTriggeredByWhen.java @@ -0,0 +1,42 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingTriggeredByWhen implements When { + + private final BlockBuilder blockBuilder; + + MessagingTriggeredByWhen(BlockBuilder blockBuilder) { + this.blockBuilder = blockBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder.addIndented( + metadata.getContract().getInput().getTriggeredBy().getExecutionCommand()) + .addEndingIfNotPresent(); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.getContract().getInput().getTriggeredBy() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingWhen.java new file mode 100644 index 0000000000..22f1c71cdc --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingWhen.java @@ -0,0 +1,55 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingWhen implements When, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final List whens = new LinkedList<>(); + + MessagingWhen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.whens.addAll(Arrays.asList(new MessagingTriggeredByWhen(this.blockBuilder), + new MessagingBodyWhen(this.blockBuilder), + new MessagingAssertThatWhen(this.blockBuilder))); + } + + @Override + public MethodVisitor apply(SingleContractMetadata singleContractMetadata) { + startBodyBlock(this.blockBuilder, "when:"); + bodyBlock(this.blockBuilder, this.whens, singleContractMetadata); + this.blockBuilder.addEmptyLine(); + return this; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return singleContractMetadata.isMessaging(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingWithBodyThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingWithBodyThen.java new file mode 100644 index 0000000000..3f22950cd9 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MessagingWithBodyThen.java @@ -0,0 +1,66 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MessagingWithBodyThen implements Then, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final ComparisonBuilder comparisonBuilder; + + private final List thens = new LinkedList<>(); + + MessagingWithBodyThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData, + ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.comparisonBuilder = comparisonBuilder; + this.thens.addAll(Arrays.asList( + new MessagingSpockNoMessageThen(this.blockBuilder, + generatedClassMetaData), + new MessagingReceiveMessageThen(this.blockBuilder, generatedClassMetaData, + this.comparisonBuilder), + new MessagingHeadersThen(this.blockBuilder, generatedClassMetaData, + this.comparisonBuilder), + new MessagingBodyThen(this.blockBuilder, generatedClassMetaData, + comparisonBuilder), + new MessagingAssertThatThen(this.blockBuilder))); + } + + @Override + public MethodVisitor apply(SingleContractMetadata singleContractMetadata) { + startBodyBlock(this.blockBuilder, "then:"); + bodyBlock(this.blockBuilder, this.thens, singleContractMetadata); + return this; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return singleContractMetadata.isMessaging() + && singleContractMetadata.getContract().getOutputMessage() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MetaDataBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MetaDataBuilder.java new file mode 100644 index 0000000000..fac0d93742 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MetaDataBuilder.java @@ -0,0 +1,47 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +class MetaDataBuilder { + + private final GeneratedTestClassBuilder parentBuilder; + + private final BlockBuilder builder; + + private final GeneratedClassMetaData metaData; + + MetaDataBuilder(GeneratedTestClassBuilder generatedTestClassBuilder) { + this.parentBuilder = generatedTestClassBuilder; + this.builder = generatedTestClassBuilder.blockBuilder; + this.metaData = generatedTestClassBuilder.generatedClassMetaData; + } + + MetaDataBuilder java() { + this.parentBuilder.metaData(new JavaClassMetaData(this.builder, this.metaData)); + return this; + } + + MetaDataBuilder groovy() { + this.parentBuilder.metaData(new GroovyClassMetaData(this.builder, this.metaData)); + return this; + } + + GeneratedTestClassBuilder build() { + return this.parentBuilder; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAcceptor.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAcceptor.java new file mode 100644 index 0000000000..35390a2f34 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAcceptor.java @@ -0,0 +1,25 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +interface MethodAcceptor { + + boolean accept(SingleContractMetadata metadata); + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAnnotationBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAnnotationBuilder.java new file mode 100644 index 0000000000..c2e2fb8ab7 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAnnotationBuilder.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +class MethodAnnotationBuilder { + + private final SingleMethodBuilder singleMethodBuilder; + + private final BlockBuilder builder; + + private final GeneratedClassMetaData metaData; + + MethodAnnotationBuilder(SingleMethodBuilder singleMethodBuilder) { + this.singleMethodBuilder = singleMethodBuilder; + this.builder = singleMethodBuilder.blockBuilder; + this.metaData = singleMethodBuilder.generatedClassMetaData; + } + + MethodAnnotationBuilder jUnit4() { + this.singleMethodBuilder.methodAnnotation( + new JUnit4MethodAnnotation(this.builder, this.metaData), + new JUnit4IgnoreMethodAnnotation(this.builder, this.metaData)); + return this; + } + + MethodAnnotationBuilder jUnit5() { + this.singleMethodBuilder.methodAnnotation( + new JUnit5MethodAnnotation(this.builder, this.metaData), + new JUnit5IgnoreMethodAnnotation(this.builder, this.metaData)); + return this; + } + + MethodAnnotationBuilder spock() { + this.singleMethodBuilder.methodAnnotation( + new SpockIgnoreMethodAnnotation(this.builder, this.metaData)); + return this; + } + + SingleMethodBuilder build() { + return this.singleMethodBuilder; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAnnotations.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAnnotations.java new file mode 100644 index 0000000000..7b86fd95c1 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodAnnotations.java @@ -0,0 +1,5 @@ +package org.springframework.cloud.contract.verifier.builder; + +interface MethodAnnotations extends MethodVisitor { + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy deleted file mode 100644 index 208800b244..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilder.groovy +++ /dev/null @@ -1,642 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import java.util.regex.Pattern - -import groovy.transform.PackageScope -import groovy.transform.TypeChecked -import org.apache.commons.text.StringEscapeUtils - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.ContractTemplate -import org.springframework.cloud.contract.spec.internal.BodyMatchers -import org.springframework.cloud.contract.spec.internal.Cookie -import org.springframework.cloud.contract.spec.internal.DslProperty -import org.springframework.cloud.contract.spec.internal.ExecutionProperty -import org.springframework.cloud.contract.spec.internal.FromFileProperty -import org.springframework.cloud.contract.spec.internal.Header -import org.springframework.cloud.contract.spec.internal.Headers -import org.springframework.cloud.contract.spec.internal.MatchingStrategy -import org.springframework.cloud.contract.spec.internal.NamedProperty -import org.springframework.cloud.contract.spec.internal.OptionalProperty -import org.springframework.cloud.contract.spec.internal.QueryParameter -import org.springframework.cloud.contract.spec.internal.RegexProperty -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.template.HandlebarsTemplateProcessor -import org.springframework.cloud.contract.verifier.template.TemplateProcessor -import org.springframework.cloud.contract.verifier.util.ContentType -import org.springframework.cloud.contract.verifier.util.ContentUtils -import org.springframework.cloud.contract.verifier.util.MapConverter -import org.springframework.util.StringUtils - -import static org.springframework.cloud.contract.verifier.util.ContentType.DEFINED -import static org.springframework.cloud.contract.verifier.util.ContentType.FORM -import static org.springframework.cloud.contract.verifier.util.ContentType.JSON -import static org.springframework.cloud.contract.verifier.util.ContentType.TEXT -import static org.springframework.cloud.contract.verifier.util.ContentType.XML -import static org.springframework.cloud.contract.verifier.util.ContentUtils.extractValue - -/** - * Main class for building method body. - * - * Do not change to {@code @CompileStatic} since it's using double dispatch. - * - * @author Olga Maciaszek-Sharma, codearte.io - * @author Tim Ysewyn - * - * @since 1.0.0 - */ -@TypeChecked -@PackageScope -abstract class MethodBodyBuilder implements ClassVerifier { - - private static final Closure GET_SERVER_VALUE = { - it instanceof DslProperty ? it.serverValue : it - } - - protected final ContractVerifierConfigProperties configProperties - protected final TemplateProcessor templateProcessor - protected final ContractTemplate contractTemplate - protected final Contract contract - protected final GeneratedClassDataForMethod classDataForMethod - private final JsonBodyVerificationBuilder jsonBodyVerificationBuilder - private final XmlBodyVerificationBuilder xmlBodyVerificationBuilder - - protected MethodBodyBuilder(ContractVerifierConfigProperties configProperties, - Contract contract, - GeneratedClassDataForMethod classDataForMethod) { - this.configProperties = configProperties - this.templateProcessor = processor() - this.contractTemplate = template() - this.contract = contract - this.classDataForMethod = classDataForMethod - this.jsonBodyVerificationBuilder = new JsonBodyVerificationBuilder(this.configProperties, - templateProcessor, contractTemplate, this.contract, - lineSuffix(), { String jsonPath -> - postProcessJsonPathCall(jsonPath) - }) - this.xmlBodyVerificationBuilder = new XmlBodyVerificationBuilder(contract, - lineSuffix()) - } - - private String byteBodyToAFileForTestMethod(FromFileProperty property, CommunicationType side) { - String newFileName = this.classDataForMethod.methodName + "_" + side.name().toLowerCase() + "_" + property.fileName() - File newFile = new File(this.classDataForMethod.testClassPath().parent.toFile(), newFileName) - // for IDE - newFile.bytes = property.asBytes() - // for plugin - generatedTestResourcesFileBytes(property, newFile) - return newFileName - } - - private void generatedTestResourcesFileBytes(FromFileProperty property, File newFile) { - java.nio.file.Path relativePath = this.configProperties.generatedTestSourcesDir. - toPath().relativize(newFile.toPath()) - File newFileInGeneratedTestSources = new File(this.configProperties.generatedTestResourcesDir, relativePath. - toString()) - newFileInGeneratedTestSources.parentFile.mkdirs() - newFileInGeneratedTestSources.bytes = property.asBytes() - } - - protected String readBytesFromFileString(FromFileProperty property, CommunicationType side) { - String fileName = byteBodyToAFileForTestMethod(property, side) - return "fileToBytes(this, \"${fileName}\")" - } - - protected String readStringFromFileString(FromFileProperty property, CommunicationType side) { - return "new String(" + readBytesFromFileString(property, side) + ")" - } - - private TemplateProcessor processor() { - return new HandlebarsTemplateProcessor() - } - - private ContractTemplate template() { - return new HandlebarsTemplateProcessor() - } - - protected ContentType getRequestContentType() { - return ContentType.UNKNOWN - } - - protected String quotedAndEscaped(String string) { - return '"' + StringEscapeUtils.escapeJava(string) + '"' - } - - /** - * Builds the response body validation code block - */ - protected abstract void validateResponseCodeBlock(BlockBuilder bb) - - /** - * Builds the response headers validation code block - */ - protected abstract void validateResponseHeadersBlock(BlockBuilder bb) - - /** - * Builds the response cookies validation code block - */ - protected abstract void validateResponseCookiesBlock(BlockBuilder bb) - - /** - * Builds the code that returns response in the string format - */ - protected abstract String getResponseAsString() - - /** - * @return the given string with comment sign if required by the given implementation - */ - protected abstract String addCommentSignIfRequired(String baseString) - - /** - * @return true if the BDD-syntax blocks should be commented out for a given framework - */ - protected abstract boolean shouldCommentOutBDDBlocks() - - /** - * Adds a colon sign at the end of each line if necessary - */ - protected abstract BlockBuilder addColonIfRequired(BlockBuilder blockBuilder) - - /** - * @return line suffix appropriate for test builder if required - */ - protected abstract Optional lineSuffix() - - /** - * Builds the code that for the given {@code property} will compare it to - * the given Object {@code value} - */ - protected abstract String getResponseBodyPropertyComparisonString(String property, Object value) - - /** - * Builds the code that for the given {@code property} will compare it to - * the given byte[] {@code value} - */ - protected abstract String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) - - /** - * Builds the code that for the given {@code property} will compare it to - * the given String {@code value} - */ - protected abstract String getResponseBodyPropertyComparisonString(String property, String value) - - /** - * Builds the code that for the given {@code property} will match it to - * the given regular expression {@code value} - */ - protected abstract String getResponseBodyPropertyComparisonString(String property, Pattern value) - - /** - * Builds the code that for the given {@code property} will match it to - * the given {@link ExecutionProperty} value - */ - protected abstract String getResponseBodyPropertyComparisonString(String property, ExecutionProperty value) - - /** - * Appends to the {@link BlockBuilder} the assertion for the given body element - */ - protected abstract void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) - - /** - * Appends to the {@link BlockBuilder} the assertion for the given body element - */ - protected abstract void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) - - /** - * Appends to the {@link BlockBuilder} the assertion for the given header path - */ - protected abstract void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) - - /** - * Appends to the {@link BlockBuilder} the assertion for the given header path - */ - protected void processHeaderElement(BlockBuilder blockBuilder, String property, RegexProperty regexProperty) { - processHeaderElement(blockBuilder, property, regexProperty.pattern) - } - - /** - * Appends to the {@link BlockBuilder} the assertion for the given header path - */ - protected abstract void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) - - /** - * Appends to the {@link BlockBuilder} the assertion for the given header path - */ - protected abstract void processHeaderElement(BlockBuilder blockBuilder, String property, String value) - - /** - * Appends to the {@link BlockBuilder} the assertion for the given header path - */ - protected abstract void processHeaderElement(BlockBuilder blockBuilder, String property, GString value) - - /** - * Appends to the {@link BlockBuilder} the assertion for the given header path - */ - protected abstract void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) - - /** - * Appends to the {@link BlockBuilder} the assertion for the given cookie path - */ - protected abstract void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) - - /** - * Appends to the {@link BlockBuilder} the assertion for the given cookie path - */ - protected abstract void processCookieElement(BlockBuilder blockBuilder, String key, String value) - - /** - * Appends to the {@link BlockBuilder} the assertion for the given cookie path - */ - protected abstract void processCookieElement(BlockBuilder blockBuilder, String key, GString value) - - /** - * Appends to the {@link BlockBuilder} the code to retrieve a value for a property - * from the list with the given index - */ - protected abstract String getPropertyInListString(String property, Integer index) - - protected abstract String convertUnicodeEscapesIfRequired(String json) - - /** - * Builds the code that returns String from a body that is plain text - */ - protected abstract String getSimpleResponseBodyString(String responseString) - - /** - * Builds the code that returns the "message". For messaging it will be an input - * message. For REST it will be an input request. - */ - protected abstract String getInputString() - - /** - * Builds the code to append a header to the request / message - */ - protected abstract String getHeaderString(Header header) - - /** - * Builds the code to append a cookie to the request / message - */ - protected abstract String getCookieString(Cookie cookie) - - /** - * Builds the code to append body to the request / message - */ - protected abstract String getBodyString(Object body) - - /** - * Builds the code to append multipart content to the request. - * Not applicable for messaging. - */ - protected abstract String getMultipartFileParameterContent(String propertyName, NamedProperty propertyValue) - - /** - * Builds the code to append a form parameter to the request. - * Not applicable for messaging. - */ - protected abstract String getParameterString(Map.Entry parameter) - - /** - * Appends the code to {@link BlockBuilder} for initial request processing - */ - protected abstract void processInput(BlockBuilder bb) - - /** - * Appends the code to {@link BlockBuilder} for the {@code //when} block - */ - protected abstract void when(BlockBuilder bb) - - /** - * Appends the code to {@link BlockBuilder} for the {@code //then} block - */ - protected abstract void then(BlockBuilder bb) - - /** - * @return a{@link org.springframework.cloud.contract.verifier.util.ContentType} for the given request - */ - protected abstract ContentType getResponseContentType() - - /** - * Converts the body into String format - */ - protected abstract String getBodyAsString() - - /** - * @return {@code true} if given section should be created - */ - protected abstract boolean hasGivenSection() - - /** - * Post processing of each JSON path entry - */ - protected String postProcessJsonPathCall(String jsonPath) { - return jsonPath - } - - /** - * Builds the test contents and appends them to {@link BlockBuilder} - */ - void appendTo(BlockBuilder blockBuilder) { - blockBuilder.startBlock() - - if (hasGivenSection()) { - givenBlock(blockBuilder) - } - whenBlock(blockBuilder) - thenBlock(blockBuilder) - - blockBuilder.endBlock() - } - - /** - * Prepares the {@code given} block section together with comments and indents - */ - protected void givenBlock(BlockBuilder bb) { - bb.addLine(addCommentSignIfRequired('given:')) - bb.startBlock() - given(bb) - bb.endBlock().addEmptyLine() - } - - /** - * Prepares the {@code when} block section together with comments and indents - */ - protected void whenBlock(BlockBuilder bb) { - bb.addLine(addCommentSignIfRequired('when:')) - bb.startBlock() - when(bb) - bb.endBlock().addEmptyLine() - } - - /** - * Prepares the {@code then} block section together with comments and indents - */ - protected void thenBlock(BlockBuilder bb) { - bb.addLine(addCommentSignIfRequired('then:')) - bb.startBlock() - then(bb) - bb.endBlock() - } - - /** - * Builds the {@code given} block section together with comments and indents - */ - protected void given(BlockBuilder bb) { - bb.addLine(getInputString()) - bb.indent() - processInput(bb) - addColonIfRequired(bb) - bb.unindent() - } - - /** - * Builds the response body verification part. The code will differ depending on the - * ContentType, type of response etc. The result will be appended to {@link BlockBuilder} - */ - protected void validateResponseBodyBlock(BlockBuilder bb, BodyMatchers bodyMatchers, Object responseBody) { - ContentType contentType = getResponseContentType() - Object convertedResponseBody = responseBody - if (convertedResponseBody instanceof FromFileProperty) { - if (convertedResponseBody.isByte()) { - byteResponseBodyCheck(bb, convertedResponseBody) - return - } - convertedResponseBody = convertedResponseBody.asString() - } - if (convertedResponseBody instanceof GString) { - convertedResponseBody = - extractValue(convertedResponseBody as GString, contentType, { Object o -> o instanceof DslProperty ? o.serverValue : o }) - } - if (TEXT != contentType && FORM != contentType && DEFINED != contentType) { - boolean dontParseStrings = contentType == JSON && convertedResponseBody instanceof Map - Closure parsingClosure = dontParseStrings ? Closure.IDENTITY : MapConverter.JSON_PARSING_CLOSURE - convertedResponseBody = MapConverter. - getTestSideValues(convertedResponseBody, parsingClosure) - } - else { - convertedResponseBody = StringEscapeUtils. - escapeJava(convertedResponseBody.toString()) - } - if (JSON == contentType) { - addJsonBodyVerification(bb, convertedResponseBody, bodyMatchers) - } - else if (XML == contentType) { - xmlBodyVerificationBuilder.addXmlResponseBodyCheck(bb, convertedResponseBody, - bodyMatchers, getResponseAsString(), shouldCommentOutBDDBlocks()) - } - else { - simpleTextResponseBodyCheck(bb, convertedResponseBody) - } - } - - - private void addJsonBodyVerification(BlockBuilder bb, Object responseBody, BodyMatchers bodyMatchers) { - Object convertedResponseBody = jsonBodyVerificationBuilder - .addJsonResponseBodyCheck(bb, responseBody, - bodyMatchers, getResponseAsString(), shouldCommentOutBDDBlocks()) - if (!(convertedResponseBody instanceof Map || convertedResponseBody instanceof List)) { - simpleTextResponseBodyCheck(bb, convertedResponseBody) - } - processBodyElement(bb, "", "", convertedResponseBody) - } - - private void simpleTextResponseBodyCheck(BlockBuilder bb, convertedResponseBody) { - bb.addLine(getSimpleResponseBodyString(getResponseAsString())) - processText(bb, "", convertedResponseBody) - addColonIfRequired(bb) - } - - protected String trailingKey(String key) { - if (key.startsWith(".")) { - return key.substring(1) - } - return key - } - - private String wrappedWithBracketsForDottedProp(String key) { - String remindingKey = trailingKey(key) - if (remindingKey.contains(".")) { - return "['${remindingKey}']" - } - return remindingKey - } - - /** - * Appends to the {@link BlockBuilder} the assertion for the given header path - */ - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) { - } - - /** - * Appends to the {@link BlockBuilder} the assertion for the given cookie - */ - protected void processCookieElement(BlockBuilder blockBuilder, String key, Object value) { - } - - /** - * Appends to the {@link BlockBuilder} the assertion for the given body element - */ - protected void processBodyElement(BlockBuilder blockBuilder, String property, Object value) { - } - - /** - * Appends to the {@link BlockBuilder} the assertion for the given body element - */ - protected void processBodyElement(BlockBuilder blockBuilder, String oldProp, String property, Object value) { - String propDiff = property - oldProp - String prop = wrappedWithBracketsForDottedProp(propDiff) - String mergedProp = StringUtils.hasText(property) ? "${oldProp}.${prop}" : "" - processBodyElement(blockBuilder, mergedProp, value) - } - - /** - * Removes unnecessary quotes - */ - protected String trimRepeatedQuotes(String toTrim) { - if (toTrim.startsWith('"')) { - return toTrim.replaceAll('"', '') - //#261 - } - else if (toTrim.startsWith('\\"') && toTrim.endsWith('\\"')) { - return toTrim.substring(2, toTrim.length() - 2) - } - return toTrim - } - - /** - * Converts the passed body into ints server side representation. All {@link DslProperty} - * will return their server side values - */ - protected Object extractServerValueFromBody(ContentType contentType, Object bodyValue) { - if (bodyValue instanceof GString) { - return extractValue(bodyValue, contentType, GET_SERVER_VALUE) - } - boolean dontParseStrings = contentType == JSON && bodyValue instanceof Map - Closure parsingClosure = dontParseStrings ? Closure.IDENTITY : MapConverter.JSON_PARSING_CLOSURE - return MapConverter.transformValues(bodyValue, GET_SERVER_VALUE, parsingClosure) - } - - protected ContentType contentType() { - Headers headers = this.contract.request?.headers ?: this.contract.input?.messageHeaders - return ContentUtils.recognizeContentTypeFromTestHeader(headers) - } - - /** - * Converts the {@link org.springframework.cloud.contract.spec.internal.QueryParameter} server side value into its String - * representation - */ - protected String resolveParamValue(QueryParameter param) { - return resolveParamValue(param.serverValue) - } - - /** - * Converts the query parameter value into String - */ - protected String resolveParamValue(Object value) { - return value.toString() - } - - /** - * Converts the query parameter DSL Property until a concrete value is reached - */ - protected String resolveParamValue(OptionalProperty value) { - return resolveParamValue(value.optionalPattern()) - } - - /** - * Converts the query parameter value into String - */ - protected String resolveParamValue(MatchingStrategy matchingStrategy) { - return matchingStrategy.serverValue.toString() - } - - /** - * Depending on the object type extracts the test side values and - * combines them into a String representation - */ - protected String getTestSideValue(Object object) { - return '"' + MapConverter.getTestSideValues(object).toString() + '"' - } - - /** - * Depending on the object type extracts the test side values and - * combines them into a String representation. Unlike the body transformation - * done via {@link MethodBodyBuilder#getTestSideValue(java.lang.Object)} will - * not try to guess the type of the value of the header (e.g. if it's a JSON). - */ - protected String getTestSideForNonBodyValue(Object object) { - if (object instanceof ExecutionProperty) { - return getTestSideValue((ExecutionProperty) object) - } - return quotedAndEscaped(MapConverter.getTestSideValuesForNonBody(object).toString()) - } - - /** - * Extracts the executable test side values and - * @return the code of the executable - */ - protected String getTestSideValue(ExecutionProperty executionProperty) { - return executionProperty.toString() - } - - - /** - * Appends to the {@link BlockBuilder} the assertion for the given body element - */ - protected void processBodyElement(BlockBuilder blockBuilder, String property, Map map) { - map.each { - processBodyElement(blockBuilder, property, it) - } - } - - /** - * Appends to the {@link BlockBuilder} the assertion for the given body element - */ - protected void processBodyElement(BlockBuilder blockBuilder, String property, List list) { - list.eachWithIndex { listElement, listIndex -> - String prop = getPropertyInListString(property, listIndex as Integer) - processBodyElement(blockBuilder, property, prop, listElement) - } - } - - /** - * Appends to {@link BlockBuilder} processing of the given String value. - */ - protected void processText(BlockBuilder blockBuilder, String property, Object value) { - if (value instanceof String && (value as String).startsWith('$')) { - String newValue = stripFirstChar((value as String)). - replaceAll('\\$value', "responseBody$property") - blockBuilder.addLine(newValue) - addColonIfRequired(blockBuilder) - } - else { - blockBuilder.addLine(getResponseBodyPropertyComparisonString(property, value)) - } - } - - private void byteResponseBodyCheck(BlockBuilder bb, - FromFileProperty convertedResponseBody) { - processText(bb, "", convertedResponseBody) - addColonIfRequired(bb) - } - - private String stripFirstChar(String s) { - return s.substring(1) - } - -} 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 deleted file mode 100644 index 7d67e90c96..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilder.groovy +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import groovy.transform.CompileStatic -import groovy.transform.PackageScope -import groovy.util.logging.Commons - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -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. - * - * @author Jakub Kubrynski, codearte.io - * - * @since 1.0.0 - */ -@Commons -@CompileStatic -@PackageScope -class MethodBuilder { - - private final String methodName - private final Contract stubContent - private final ContractVerifierConfigProperties configProperties - private final GeneratedClassDataForMethod generatedClassDataForMethod - private final boolean ignored - - private MethodBuilder(String methodName, Contract stubContent, ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod generatedClassDataForMethod, boolean ignored) { - this.ignored = ignored - this.stubContent = stubContent - this.methodName = methodName - this.configProperties = configProperties - this.generatedClassDataForMethod = generatedClassDataForMethod - } - - /** - * A factory method that creates a {@link MethodBuilder} for the given arguments - */ - static MethodBuilder createTestMethod(ContractMetadata contract, File stubsFile, Contract stubContent, ContractVerifierConfigProperties configProperties, SingleTestGenerator.GeneratedClassData generatedClassData) { - if (log.isDebugEnabled()) { - log.debug("Stub content Groovy DSL [$stubContent]") - } - String methodName = methodName(contract, stubsFile, stubContent) - return new MethodBuilder(methodName, stubContent, configProperties, - new GeneratedClassDataForMethod(generatedClassData, methodName), contract.ignored || stubContent.ignored) - } - - static String methodName(ContractMetadata contract, File stubsFile, Contract stubContent) { - if (stubContent.name) { - String name = NamesUtil. - camelCase(NamesUtil.convertIllegalPackageChars(stubContent.name)) - if (log.isDebugEnabled()) { - log.debug("Overriding the default test name with [" + name + "]") - } - return name - } - else if (contract.convertedContract.size() > 1) { - int index = contract.convertedContract.findIndexOf { it == stubContent } - String name = "${camelCasedMethodFromFileName(stubsFile)}_${index}" - if (log.isDebugEnabled()) { - log.debug("Scenario found. The method name will be [" + name + "]") - } - return name - } - String name = camelCasedMethodFromFileName(stubsFile) - if (log.isDebugEnabled()) { - log.debug("The method name will be [" + name + "]") - } - return name - } - - private static String camelCasedMethodFromFileName(File stubsFile) { - return NamesUtil.camelCase(NamesUtil.convertIllegalMethodNameChars(NamesUtil. - toLastDot(NamesUtil.afterLast(stubsFile.path, File.separator)))) - } - - /** - * Appends to the {@link BlockBuilder} the contents of the test - */ - void appendTo(BlockBuilder blockBuilder) { - if (isJUnitType()) { - blockBuilder.addLine('@Test') - } - if (ignored) { - blockBuilder.addLine(configProperties.testFramework.ignoreAnnotation) - } - blockBuilder. - addLine(configProperties.testFramework.methodModifier + "validate_$methodName() throws Exception {") - getMethodBodyBuilder().appendTo(blockBuilder) - blockBuilder.addLine('}') - } - - private MethodBodyBuilder getMethodBodyBuilder() { - if (stubContent.input || stubContent.outputMessage) { - if (isJUnitType()) { - return new JUnitMessagingMethodBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod) - } - return new SpockMessagingMethodBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod) - } - if (configProperties.testMode == TestMode.JAXRSCLIENT) { - if (isJUnitType()) { - return new JaxRsClientJUnitMethodBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod) - } - return new JaxRsClientSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod) - } - else if (configProperties.testMode == TestMode.WEBTESTCLIENT) { - if (isJUnitType()) { - return new WebTestClientJUnitMethodBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod) - } - return new HttpSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod) - } - else if (configProperties.testMode == TestMode.EXPLICIT) { - if (isJUnitType()) { - return new ExplicitJUnitMethodBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod) - } - // in Groovy we're using def so we don't have to update the imports - return new HttpSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod) - } - else if (configProperties.testFramework == SPOCK) { - return new HttpSpockMethodRequestProcessingBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod) - } - return new MockMvcJUnitMethodBodyBuilder(stubContent, configProperties, this.generatedClassDataForMethod) - } - - private boolean isJUnitType() { - return JUNIT == configProperties.testFramework || JUNIT5 == configProperties.testFramework - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodMetadata.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodMetadata.java new file mode 100644 index 0000000000..4980c3365e --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodMetadata.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +/** + * Describes metadata of a single method. + */ +interface MethodMetadata extends Acceptor { + + // validate_foo() + MethodMetadata name(SingleContractMetadata metadata); + + // public + MethodMetadata modifier(); + + // void + MethodMetadata returnType(); + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodMetadataBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodMetadataBuilder.java new file mode 100644 index 0000000000..1ec22719aa --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodMetadataBuilder.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +class MethodMetadataBuilder { + + private final SingleMethodBuilder singleMethodBuilder; + + private final BlockBuilder builder; + + private final GeneratedClassMetaData metaData; + + MethodMetadataBuilder(SingleMethodBuilder singleMethodBuilder) { + this.singleMethodBuilder = singleMethodBuilder; + this.builder = singleMethodBuilder.blockBuilder; + this.metaData = singleMethodBuilder.generatedClassMetaData; + } + + MethodMetadataBuilder jUnit() { + this.singleMethodBuilder + .methodMetadata(new JUnitMethodMetadata(this.builder, this.metaData)); + return this; + } + + MethodMetadataBuilder spock() { + this.singleMethodBuilder + .methodMetadata(new SpockMethodMetadata(this.builder, this.metaData)); + return this; + } + + SingleMethodBuilder build() { + return this.singleMethodBuilder; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodVisitor.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodVisitor.java new file mode 100644 index 0000000000..0cc45f0ca5 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MethodVisitor.java @@ -0,0 +1,26 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.function.Function; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +interface MethodVisitor + extends MethodAcceptor, Function> { + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcAcceptor.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcAcceptor.java new file mode 100644 index 0000000000..6e87bec3e1 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcAcceptor.java @@ -0,0 +1,30 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestMode; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +interface MockMvcAcceptor { + + default boolean acceptType(GeneratedClassMetaData generatedClassMetaData, + SingleContractMetadata singleContractMetadata) { + return generatedClassMetaData.configProperties.getTestMode() == TestMode.MOCKMVC + && singleContractMetadata.isHttp(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcAsyncWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcAsyncWhen.java new file mode 100644 index 0000000000..a89903c388 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcAsyncWhen.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.Response; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MockMvcAsyncWhen implements When, MockMvcAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + MockMvcAsyncWhen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + Response response = metadata.getContract().getResponse(); + if (response.getAsync()) { + this.blockBuilder.addIndented(".when().async()"); + } + if (response.getDelay() != null) { + this.blockBuilder.addIndented( + ".timeout(" + response.getDelay().getServerValue() + ")"); + } + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + boolean accept = acceptType(this.generatedClassMetaData, metadata); + if (!accept) { + return false; + } + Response response = metadata.getContract().getResponse(); + return response.getAsync() || response.getDelay() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcBodyGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcBodyGiven.java new file mode 100644 index 0000000000..a2caa2bb17 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcBodyGiven.java @@ -0,0 +1,95 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.spec.internal.FromFileProperty; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.ContentType; + +class MockMvcBodyGiven implements Given { + + private final BlockBuilder blockBuilder; + + private final BodyReader bodyReader; + + private final BodyParser bodyParser; + + MockMvcBodyGiven(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData, BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.bodyReader = new BodyReader(generatedClassMetaData); + this.bodyParser = bodyParser; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + processInput(this.blockBuilder, metadata); + this.blockBuilder.addEmptyLine(); + return this; + } + + private void processInput(BlockBuilder bb, SingleContractMetadata metadata) { + Object body; + Request request = metadata.getContract().getRequest(); + Object serverValue = request.getBody().getServerValue(); + if (serverValue instanceof ExecutionProperty + || serverValue instanceof FromFileProperty) { + body = request.getBody().getServerValue(); + } + else { + body = this.bodyParser.requestBodyAsString(metadata); + } + bb.addIndented(getBodyString(metadata, body)); + } + + private String getBodyString(SingleContractMetadata metadata, Object body) { + String value; + if (body instanceof ExecutionProperty) { + value = body.toString(); + } + else if (body instanceof FromFileProperty) { + FromFileProperty fileProperty = (FromFileProperty) body; + value = fileProperty.isByte() + ? this.bodyReader.readBytesFromFileString(metadata, fileProperty, + CommunicationType.REQUEST) + : this.bodyReader.readStringFromFileString(metadata, fileProperty, + CommunicationType.REQUEST); + } + else { + String escaped = escapeRequestSpecialChars(metadata, body.toString()); + value = this.bodyParser.quotedEscapedLongText(escaped); + } + return ".body(" + value + ")"; + } + + private String escapeRequestSpecialChars(SingleContractMetadata metadata, + String string) { + if (metadata.getInputTestContentType() == ContentType.JSON) { + return string.replaceAll("\\\\n", "\\\\\\\\n"); + } + return string; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Request request = metadata.getContract().getRequest(); + return request != null && request.getBody() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcCookiesGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcCookiesGiven.java new file mode 100644 index 0000000000..faa86133ce --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcCookiesGiven.java @@ -0,0 +1,74 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Iterator; + +import org.springframework.cloud.contract.spec.internal.Cookie; +import org.springframework.cloud.contract.spec.internal.MatchingStrategy; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MockMvcCookiesGiven implements Given { + + private final BlockBuilder blockBuilder; + + MockMvcCookiesGiven(BlockBuilder blockBuilder) { + this.blockBuilder = blockBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + processInput(this.blockBuilder, metadata.getContract().getRequest()); + return this; + } + + private void processInput(BlockBuilder bb, Request request) { + Iterator iterator = request.getCookies().getEntries().iterator(); + while (iterator.hasNext()) { + Cookie cookie = iterator.next(); + if (ofAbsentType(cookie)) { + return; + } + if (iterator.hasNext()) { + this.blockBuilder.addLine(string(cookie)); + } + else { + this.blockBuilder.addIndented(string(cookie)); + } + } + } + + private String string(Cookie cookie) { + return ".cookie(" + ContentHelper.getTestSideForNonBodyValue(cookie.getKey()) + + ", " + ContentHelper.getTestSideForNonBodyValue(cookie.getServerValue()) + + ")"; + } + + private boolean ofAbsentType(Cookie cookie) { + return cookie.getServerValue() instanceof MatchingStrategy + && MatchingStrategy.Type.ABSENT + .equals(((MatchingStrategy) cookie.getServerValue()).getType()); + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Request request = metadata.getContract().getRequest(); + return request != null && request.getCookies() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcHeadersGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcHeadersGiven.java new file mode 100644 index 0000000000..d691550453 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcHeadersGiven.java @@ -0,0 +1,75 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Iterator; + +import org.springframework.cloud.contract.spec.internal.Header; +import org.springframework.cloud.contract.spec.internal.Headers; +import org.springframework.cloud.contract.spec.internal.MatchingStrategy; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MockMvcHeadersGiven implements Given { + + private final BlockBuilder blockBuilder; + + MockMvcHeadersGiven(BlockBuilder blockBuilder) { + this.blockBuilder = blockBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + processInput(this.blockBuilder, metadata.getContract().getRequest().getHeaders()); + return this; + } + + private void processInput(BlockBuilder bb, Headers headers) { + Iterator
iterator = headers.getEntries().iterator(); + while (iterator.hasNext()) { + Header header = iterator.next(); + if (ofAbsentType(header)) { + return; + } + if (iterator.hasNext()) { + bb.addLine(string(header)); + } + else { + bb.addIndented(string(header)); + } + } + } + + private String string(Header header) { + return ".header(" + ContentHelper.getTestSideForNonBodyValue(header.getName()) + + ", " + ContentHelper.getTestSideForNonBodyValue(header.getServerValue()) + + ")"; + } + + private boolean ofAbsentType(Header header) { + return header.getServerValue() instanceof MatchingStrategy + && MatchingStrategy.Type.ABSENT + .equals(((MatchingStrategy) header.getServerValue()).getType()); + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Request request = metadata.getContract().getRequest(); + return request != null && request.getHeaders() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcJUnitMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcJUnitMethodBodyBuilder.groovy deleted file mode 100644 index 106f23f82d..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcJUnitMethodBodyBuilder.groovy +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import groovy.transform.CompileStatic -import groovy.transform.PackageScope - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties - -/** - * A {@link JUnitMethodBodyBuilder} implementation that uses MockMvc to send requests. - * - * @author Olga Maciaszek-Sharma, codearte.io - * - * @since 1.0.0 - */ -@CompileStatic -@PackageScope -class MockMvcJUnitMethodBodyBuilder extends RestAssuredJUnitMethodBodyBuilder { - - MockMvcJUnitMethodBodyBuilder(Contract stubDefinition, ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(stubDefinition, configProperties, classDataForMethod) - } - - @Override - protected String returnedResponseType() { - return 'ResponseOptions' - } - - @Override - protected String returnedRequestType() { - return 'MockMvcRequestSpecification' - } - -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMultipartGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMultipartGiven.java new file mode 100644 index 0000000000..502320528b --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMultipartGiven.java @@ -0,0 +1,88 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Map; + +import org.springframework.cloud.contract.spec.internal.NamedProperty; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +import static org.springframework.cloud.contract.verifier.util.ContentUtils.getJavaMultipartFileParameterContent; + +class MockMvcMultipartGiven implements Given { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final BodyReader bodyReader; + + private final BodyParser bodyParser; + + MockMvcMultipartGiven(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData, BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.bodyReader = new BodyReader(generatedClassMetaData); + this.bodyParser = bodyParser; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + getMultipartParameters(metadata).entrySet().forEach(entry -> this.blockBuilder + .addLine(getMultipartParameterLine(metadata, entry))); + return this; + } + + private String getMultipartParameterLine(SingleContractMetadata metadata, + Map.Entry parameter) { + if (parameter.getValue() instanceof NamedProperty) { + return ".multiPart(" + getMultipartFileParameterContent(metadata, + parameter.getKey(), (NamedProperty) parameter.getValue()) + ")"; + } + return getParameterString(parameter); + } + + @SuppressWarnings("unchecked") + private Map getMultipartParameters(SingleContractMetadata metadata) { + return (Map) metadata.getContract().getRequest().getMultipart() + .getServerValue(); + } + + private String getMultipartFileParameterContent(SingleContractMetadata metadata, + String propertyName, NamedProperty propertyValue) { + return getJavaMultipartFileParameterContent(propertyName, propertyValue, + fileProp -> this.bodyReader.readBytesFromFileString(metadata, fileProp, + CommunicationType.REQUEST)); + } + + private String getParameterString(Map.Entry parameter) { + return ".param(" + this.bodyParser.quotedShortText(parameter.getKey()) + ", " + + this.bodyParser.quotedShortText(parameter.getValue()) + ")"; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Request request = metadata.getContract().getRequest(); + return request != null && request.getMultipart() != null + && this.generatedClassMetaData.configProperties + .getTestFramework() != TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcQueryParamsWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcQueryParamsWhen.java new file mode 100644 index 0000000000..8ee7a2a8ae --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcQueryParamsWhen.java @@ -0,0 +1,84 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.MatchingStrategy; +import org.springframework.cloud.contract.spec.internal.QueryParameter; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.spec.internal.Url; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MockMvcQueryParamsWhen implements When, MockMvcAcceptor, QueryParamsResolver { + + private static final String QUERY_PARAM_METHOD = "queryParam"; + + private final BlockBuilder blockBuilder; + + private final BodyParser bodyParser; + + MockMvcQueryParamsWhen(BlockBuilder blockBuilder, BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.bodyParser = bodyParser; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + Request request = metadata.getContract().getRequest(); + Url url = getUrl(request); + addQueryParameters(url); + return this; + } + + private Url getUrl(Request request) { + if (request.getUrl() != null) { + return request.getUrl(); + } + if (request.getUrlPath() != null) { + return request.getUrlPath(); + } + throw new IllegalStateException("URL is not set!"); + } + + private void addQueryParameters(Url buildUrl) { + buildUrl.getQueryParameters().getParameters().stream() + .filter(this::allowedQueryParameter).forEach(this::addQueryParameter); + } + + private boolean allowedQueryParameter(Object o) { + if (o instanceof QueryParameter) { + return allowedQueryParameter(((QueryParameter) o).getServerValue()); + } + else if (o instanceof MatchingStrategy) { + return !MatchingStrategy.Type.ABSENT.equals(((MatchingStrategy) o).getType()); + } + return true; + } + + private void addQueryParameter(QueryParameter queryParam) { + this.blockBuilder.addLine("." + QUERY_PARAM_METHOD + "(" + + this.bodyParser.quotedLongText(queryParam.getName()) + "," + + this.bodyParser.quotedLongText(resolveParamValue(queryParam)) + ")"); + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Request request = metadata.getContract().getRequest(); + Url url = getUrl(request); + return url.getQueryParameters() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRequestGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRequestGiven.java new file mode 100644 index 0000000000..c43130a083 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRequestGiven.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MockMvcRequestGiven implements Given, MockMvcAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + MockMvcRequestGiven(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder.addIndented("MockMvcRequestSpecification request = given()"); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return acceptType(this.generatedClassMetaData, metadata); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcResponseWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcResponseWhen.java new file mode 100644 index 0000000000..4e0b7fad80 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcResponseWhen.java @@ -0,0 +1,43 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class MockMvcResponseWhen implements When, MockMvcAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + MockMvcResponseWhen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder.addIndented("ResponseOptions response = given().spec(request)"); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return acceptType(this.generatedClassMetaData, metadata); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRestAssuredImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRestAssuredImports.java new file mode 100644 index 0000000000..577ccddb58 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRestAssuredImports.java @@ -0,0 +1,59 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestMode; + +class MockMvcRestAssuredImports implements Imports, RestAssuredVerifier { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + @Deprecated + private static final String[] REST_ASSURED_2_IMPORTS = { + "com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification", + "com.jayway.restassured.response.ResponseOptions" }; + + private static final String[] REST_ASSURED_3_IMPORTS = { + "io.restassured.module.mockmvc.specification.MockMvcRequestSpecification", + "io.restassured.response.ResponseOptions" }; + + MockMvcRestAssuredImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream( + isRestAssured2Present() ? REST_ASSURED_2_IMPORTS : REST_ASSURED_3_IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestMode() == TestMode.MOCKMVC + && this.generatedClassMetaData.isAnyHttp(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRestAssuredStaticImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRestAssuredStaticImports.java new file mode 100644 index 0000000000..28b0de4638 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcRestAssuredStaticImports.java @@ -0,0 +1,56 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestMode; + +class MockMvcRestAssuredStaticImports implements Imports, RestAssuredVerifier { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] REST_ASSURED_2_IMPORTS = { + "com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*" }; + + private static final String[] REST_ASSURED_3_IMPORTS = { + "io.restassured.module.mockmvc.RestAssuredMockMvc.*" }; + + MockMvcRestAssuredStaticImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream( + isRestAssured2Present() ? REST_ASSURED_2_IMPORTS : REST_ASSURED_3_IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestMode() == TestMode.MOCKMVC + && this.generatedClassMetaData.isAnyHttp(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcUrlWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcUrlWhen.java new file mode 100644 index 0000000000..527914ee65 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcUrlWhen.java @@ -0,0 +1,69 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.spec.internal.Url; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +class MockMvcUrlWhen implements When, MockMvcAcceptor, QueryParamsResolver { + + private final BlockBuilder blockBuilder; + + private final BodyParser bodyParser; + + MockMvcUrlWhen(BlockBuilder blockBuilder, BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.bodyParser = bodyParser; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + Request request = metadata.getContract().getRequest(); + Url url = getUrl(request); + addUrl(url, request); + return this; + } + + private Url getUrl(Request request) { + if (request.getUrl() != null) { + return request.getUrl(); + } + if (request.getUrlPath() != null) { + return request.getUrlPath(); + } + throw new IllegalStateException("URL is not set!"); + } + + private void addUrl(Url buildUrl, Request request) { + Object testSideUrl = MapConverter.getTestSideValues(buildUrl); + String method = request.getMethod().getServerValue().toString().toLowerCase(); + String url = testSideUrl.toString(); + if (!(testSideUrl instanceof ExecutionProperty)) { + url = this.bodyParser.quotedShortText(testSideUrl.toString()); + } + this.blockBuilder.addIndented("." + method + "(" + url + ")"); + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return true; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/NameProvider.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/NameProvider.java new file mode 100644 index 0000000000..5908772677 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/NameProvider.java @@ -0,0 +1,82 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.io.File; +import java.util.Collection; + +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.file.ContractMetadata; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.NamesUtil; +import org.springframework.util.StringUtils; + +class NameProvider { + + private static final Log log = LogFactory.getLog(NameProvider.class); + + String methodName(SingleContractMetadata singleContractMetadata) { + return "validate_" + generateMethodName(singleContractMetadata); + } + + private String generateMethodName(SingleContractMetadata singleContractMetadata) { + ContractMetadata contractMetadata = singleContractMetadata.getContractMetadata(); + File stubsFile = contractMetadata.getPath().toFile(); + Contract stubContent = singleContractMetadata.getContract(); + if (StringUtils.hasText(stubContent.getName())) { + String name = NamesUtil.camelCase( + NamesUtil.convertIllegalPackageChars(stubContent.getName())); + if (log.isDebugEnabled()) { + log.debug("Overriding the default test name with [" + name + "]"); + } + return name; + } + else if (contractMetadata.getConvertedContract().size() > 1) { + int index = findIndexOf(contractMetadata.getConvertedContract(), stubContent); + String name = camelCasedMethodFromFileName(stubsFile) + "_" + index; + if (log.isDebugEnabled()) { + log.debug("Scenario found. The method name will be [" + name + "]"); + } + return name; + } + String name = camelCasedMethodFromFileName(stubsFile); + if (StringUtils.hasText(name) && log.isDebugEnabled()) { + log.debug("The method name will be [" + name + "]"); + } + return name; + } + + private int findIndexOf(Collection contracts, Contract stubContent) { + int i = 0; + for (Contract contract : contracts) { + if (contract.equals(stubContent)) { + return i; + } + i++; + } + return -1; + } + + private String camelCasedMethodFromFileName(File stubsFile) { + return NamesUtil.camelCase(NamesUtil.convertIllegalMethodNameChars(NamesUtil + .toLastDot(NamesUtil.afterLast(stubsFile.getPath(), File.separator)))); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/OurCallable.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/OurCallable.java new file mode 100644 index 0000000000..449f478396 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/OurCallable.java @@ -0,0 +1,23 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface OurCallable { + + T call(); + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/QueryParamsResolver.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/QueryParamsResolver.java new file mode 100644 index 0000000000..23663079a0 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/QueryParamsResolver.java @@ -0,0 +1,41 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.MatchingStrategy; +import org.springframework.cloud.contract.spec.internal.OptionalProperty; +import org.springframework.cloud.contract.spec.internal.QueryParameter; + +interface QueryParamsResolver { + + /** + * Converts the query parameter value into String + */ + default String resolveParamValue(Object value) { + if (value instanceof QueryParameter) { + return resolveParamValue(((QueryParameter) value).getServerValue()); + } + else if (value instanceof OptionalProperty) { + return resolveParamValue(((OptionalProperty) value).optionalPattern()); + } + else if (value instanceof MatchingStrategy) { + return ((MatchingStrategy) value).getServerValue().toString(); + } + return value.toString(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RequestProcessingMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RequestProcessingMethodBodyBuilder.groovy deleted file mode 100644 index ca618093b0..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RequestProcessingMethodBodyBuilder.groovy +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import groovy.json.JsonOutput -import groovy.transform.PackageScope -import groovy.transform.TypeChecked -import groovy.transform.TypeCheckingMode - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.BodyMatchers -import org.springframework.cloud.contract.spec.internal.Cookie -import org.springframework.cloud.contract.spec.internal.ExecutionProperty -import org.springframework.cloud.contract.spec.internal.FromFileProperty -import org.springframework.cloud.contract.spec.internal.Header -import org.springframework.cloud.contract.spec.internal.MatchingStrategy -import org.springframework.cloud.contract.spec.internal.NamedProperty -import org.springframework.cloud.contract.spec.internal.QueryParameter -import org.springframework.cloud.contract.spec.internal.Request -import org.springframework.cloud.contract.spec.internal.Response -import org.springframework.cloud.contract.spec.internal.Url -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.util.ContentType -import org.springframework.cloud.contract.verifier.util.ContentUtils -import org.springframework.cloud.contract.verifier.util.MapConverter - -import static org.springframework.cloud.contract.verifier.util.ContentUtils.evaluateContentType - -/** - * An abstraction for creating a test method that includes processing of an HTTP request - * - * Do not change to {@code @CompileStatic} since it's using double dispatch. - * - * @author Olga Maciaszek-Sharma, codearte.io - * @author Tim Ysewyn - * - * @since 1.0.0 - */ -@TypeChecked -@PackageScope -abstract class RequestProcessingMethodBodyBuilder extends MethodBodyBuilder { - - protected final Request request - protected final Response response - private static final String DOUBLE_QUOTE = '"' - private static final String QUERY_PARAM_METHOD = 'queryParam' - - RequestProcessingMethodBodyBuilder(Contract stubDefinition, ContractVerifierConfigProperties configProperties, GeneratedClassDataForMethod classDataForMethod) { - super(configProperties, stubDefinition, classDataForMethod) - this.request = stubDefinition.request - this.response = stubDefinition.response - } - - protected String escapeRequestSpecialChars(String string) { - if (getRequestContentType() == ContentType.JSON) { - return string - .replaceAll('\\\\n', '\\\\\\\\n') - } - return string - } - - /** - * @return code used to retrieve a response for the given {@link Request} - */ - protected abstract String getInputString(Request request) - - @Override - protected boolean hasGivenSection() { - return true - } - - /** - * @return {@code true} if a response body is expected - */ - protected boolean expectsResponseBody() { - return response.body != null - } - - /** - * @return {@code true} if the query parameter is allowed - */ - protected boolean allowedQueryParameter(QueryParameter param) { - return allowedQueryParameter(param.serverValue) - } - - /** - * @return {@code true} if the query parameter is allowed - */ - protected boolean allowedQueryParameter(MatchingStrategy matchingStrategy) { - return matchingStrategy.type != MatchingStrategy.Type.ABSENT - } - - /** - * @return {@code true} if the query parameter is allowed - */ - protected boolean allowedQueryParameter(Object o) { - return true - } - - @Override - protected void processInput(BlockBuilder bb) { - request.headers?.executeForEachHeader { Header header -> - if (headerOfAbsentType(header)) { - return - } - bb.addLine(getHeaderString(header)) - } - - request.cookies?.executeForEachCookie { Cookie cookie -> - if (cookieOfAbsentType(cookie)) { - return - } - bb.addLine(getCookieString(cookie)) - } - - if (request.body) { - Object body = null - switch (request.body.serverValue) { - case ExecutionProperty: - case FromFileProperty: - body = request.body?.serverValue - break - default: - body = getBodyAsString() - } - bb.addLine(getBodyString(body)) - } - if (request.multipart) { - multipartParameters?.each { Map.Entry entry -> - bb. - addLine(getMultipartParameterLine(entry)) - } - } - } - - protected boolean headerOfAbsentType(Header header) { - return header.serverValue instanceof MatchingStrategy && - ((MatchingStrategy) header.serverValue).type == MatchingStrategy.Type.ABSENT - } - - protected boolean cookieOfAbsentType(Cookie cookie) { - return cookie.serverValue instanceof MatchingStrategy && - ((MatchingStrategy) cookie.serverValue).type == MatchingStrategy.Type.ABSENT - } - - @Override - protected void when(BlockBuilder bb) { - bb.addLine(getInputString(request)) - bb.indent() - - Url url = getUrl(request) - addQueryParameters(url, bb) - addAsyncIfRequired(bb) - addUrl(url, bb) - addColonIfRequired(bb) - bb.unindent() - } - - private void addAsyncIfRequired(BlockBuilder bb) { - if (response.async) { - bb.addLine('.when().async()') - } - if (response.delay) { - bb.addLine(".timeout(${response.delay.serverValue})") - } - } - - @TypeChecked(TypeCheckingMode.SKIP) - protected addQueryParameters(Url buildUrl, BlockBuilder bb) { - if (hasQueryParams(buildUrl)) { - List queryParameters = buildUrl.queryParameters.parameters. - findAll(this.&allowedQueryParameter) - for (queryParam in queryParameters) { - addQueryParameter(queryParam, bb) - } - } - } - - @TypeChecked(TypeCheckingMode.SKIP) - protected addQueryParameter(QueryParameter queryParam, BlockBuilder bb) { - bb.addLine(".${QUERY_PARAM_METHOD}(${DOUBLE_QUOTE}${queryParam.name}" - + - "${DOUBLE_QUOTE},${DOUBLE_QUOTE}${resolveParamValue(queryParam).toString()}${DOUBLE_QUOTE})") - } - - protected addUrl(Url buildUrl, BlockBuilder bb) { - Object testSideUrl = MapConverter.getTestSideValues(buildUrl) - String method = request.method.serverValue.toString().toLowerCase() - String url = testSideUrl.toString() - if (!(testSideUrl instanceof ExecutionProperty)) { - url = "${DOUBLE_QUOTE}${testSideUrl.toString()}${DOUBLE_QUOTE}" - } - bb.addLine(/.${method}(${url})/) - } - - @Override - protected void then(BlockBuilder bb) { - validateResponseCodeBlock(bb) - if (response.headers) { - validateResponseHeadersBlock(bb) - } - if (response.cookies) { - validateResponseCookiesBlock(bb) - } - if (response.body) { - bb.endBlock() - bb.addLine(addCommentSignIfRequired('and:')).startBlock() - validateResponseBodyBlock(bb, response.bodyMatchers, response.body.serverValue) - } - } - - @Override - protected void validateResponseBodyBlock(BlockBuilder bb, BodyMatchers bodyMatchers, Object responseBody) { - super.validateResponseBodyBlock(bb, bodyMatchers, responseBody) - String newBody = this.templateProcessor.transform(request, bb.toString()) - bb.updateContents(newBody) - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, GString value) { - String gstringValue = ContentUtils. - extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString() - processHeaderElement(blockBuilder, property, gstringValue) - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, GString value) { - String gStringValue = ContentUtils. - extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString() - processCookieElement(blockBuilder, key, gStringValue) - } - - @Override - protected ContentType getResponseContentType() { - return evaluateContentType(response?.headers, response?.body?.serverValue) - } - - @Override - protected String getBodyAsString() { - ContentType contentType = contentType() - Object bodyValue = - extractServerValueFromBody(contentType, request.body.serverValue) - if (contentType == ContentType.FORM) { - if (bodyValue instanceof Map) { - // [a:3, b:4] == "a=3&b=4" - return ((Map) bodyValue).collect { - convertUnicodeEscapesIfRequired(it.key.toString() + "=" + it.value) - }.join("&") - } - else if (bodyValue instanceof List) { - // ["a=3", "b=4"] == "a=3&b=4" - return ((List) bodyValue).collect { - convertUnicodeEscapesIfRequired(it.toString()) - }.join("&") - } - } - else { - String json = new JsonOutput().toJson(bodyValue) - json = convertUnicodeEscapesIfRequired(json) - return trimRepeatedQuotes(json) - } - } - - /** - * @return a map of server side multipart parameters - */ - protected Map getMultipartParameters() { - return (Map) request?.multipart?.serverValue - } - - /** - * Maps the {@link Request} into a {@link ContentType} - */ - protected ContentType getRequestContentType() { - return evaluateContentType(request?.headers, request?.body?.serverValue) - } - - /** - * @return a String URL from {@link Request}'s test side values. It can be - * a concrete value of the URL or a path. - */ - protected Url getUrl(Request request) { - if (request.url) { - return request.url - } - if (request.urlPath) { - return request.urlPath - } - throw new IllegalStateException("URL is not set!") - } - - /** - * @return a line of code to send a multi part parameter in the request - */ - protected String getMultipartParameterLine(Map.Entry parameter) { - if (parameter.value instanceof NamedProperty) { - return ".multiPart(${getMultipartFileParameterContent(parameter.key, (NamedProperty) parameter.value)})" - } - return getParameterString(parameter) - } - - private boolean hasQueryParams(Url url) { - return url.queryParameters - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredBodyParser.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredBodyParser.java new file mode 100644 index 0000000000..abdd1952bb --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredBodyParser.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface RestAssuredBodyParser extends BodyParser { + + BodyParser INSTANCE = new RestAssuredBodyParser() { + }; + + @Override + default String responseAsString() { + return "response.getBody().asString()"; + } + + @Override + default String byteArrayString() { + return "response.getBody().asByteArray()"; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredCookiesThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredCookiesThen.java new file mode 100644 index 0000000000..e4eb20eb09 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredCookiesThen.java @@ -0,0 +1,61 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.Response; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class RestAssuredCookiesThen implements Then, MockMvcAcceptor, CookieElementProcessor { + + private final BlockBuilder blockBuilder; + + private final ComparisonBuilder comparisonBuilder; + + RestAssuredCookiesThen(BlockBuilder blockBuilder, + ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.comparisonBuilder = comparisonBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + processCookies(metadata); + return this; + } + + @Override + public ComparisonBuilder comparisonBuilder() { + return this.comparisonBuilder; + } + + @Override + public BlockBuilder blockBuilder() { + return this.blockBuilder; + } + + @Override + public String cookieKey(String key) { + return "response.cookie(\"" + key + "\")"; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Response response = metadata.getContract().getResponse(); + return response.getCookies() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredGiven.java new file mode 100644 index 0000000000..387dc30fba --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredGiven.java @@ -0,0 +1,77 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.cloud.contract.verifier.config.TestMode; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class RestAssuredGiven implements Given, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final List requestGivens = new LinkedList<>(); + + private final List bodyGivens = new LinkedList<>(); + + RestAssuredGiven(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData, BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.requestGivens.addAll(Arrays.asList( + new MockMvcRequestGiven(blockBuilder, generatedClassMetaData), + new SpockMockMvcRequestGiven(blockBuilder, generatedClassMetaData), + new ExplicitRequestGiven(blockBuilder, generatedClassMetaData), + new WebTestClientRequestGiven(blockBuilder, generatedClassMetaData))); + this.bodyGivens.addAll(Arrays.asList(new MockMvcHeadersGiven(blockBuilder), + new MockMvcCookiesGiven(blockBuilder), + new MockMvcBodyGiven(blockBuilder, generatedClassMetaData, bodyParser), + new MockMvcMultipartGiven(blockBuilder, generatedClassMetaData, + bodyParser), + new SpockMockMvcMultipartGiven(blockBuilder, generatedClassMetaData, + bodyParser))); + } + + @Override + public MethodVisitor apply(SingleContractMetadata singleContractMetadata) { + startBodyBlock(this.blockBuilder, "given:"); + addRequestGivenLine(singleContractMetadata); + indentedBodyBlock(this.blockBuilder, this.bodyGivens, singleContractMetadata); + return this; + } + + private void addRequestGivenLine(SingleContractMetadata singleContractMetadata) { + this.requestGivens.stream().filter(given -> given.accept(singleContractMetadata)) + .findFirst() + .orElseThrow(() -> new IllegalStateException( + "No matching request building Given implementation for Rest Assured")) + .apply(singleContractMetadata); + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return singleContractMetadata.isHttp() + && this.generatedClassMetaData.configProperties + .getTestMode() != TestMode.JAXRSCLIENT; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredHeadersThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredHeadersThen.java new file mode 100644 index 0000000000..a11b9493c6 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredHeadersThen.java @@ -0,0 +1,89 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Iterator; + +import org.springframework.cloud.contract.spec.internal.ExecutionProperty; +import org.springframework.cloud.contract.spec.internal.Header; +import org.springframework.cloud.contract.spec.internal.Headers; +import org.springframework.cloud.contract.spec.internal.NotToEscapePattern; +import org.springframework.cloud.contract.spec.internal.Response; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +class RestAssuredHeadersThen implements Then, MockMvcAcceptor { + + private final BlockBuilder blockBuilder; + + private final ComparisonBuilder comparisonBuilder; + + RestAssuredHeadersThen(BlockBuilder blockBuilder, + ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.comparisonBuilder = comparisonBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + Response response = metadata.getContract().getResponse(); + Headers headers = response.getHeaders(); + Iterator
iterator = headers.getEntries().iterator(); + while (iterator.hasNext()) { + Header header = iterator.next(); + String text = processHeaderElement(header.getName(), + header.getServerValue() instanceof NotToEscapePattern + ? header.getServerValue() + : MapConverter.getTestSideValues(header.getServerValue())); + if (iterator.hasNext()) { + this.blockBuilder.addLineWithEnding(text); + } + else { + this.blockBuilder.addIndented(text); + } + } + this.blockBuilder.addEndingIfNotPresent(); + return this; + } + + private String processHeaderElement(String property, Object value) { + if (value instanceof NotToEscapePattern) { + return this.comparisonBuilder + .assertThat("response.header(\"" + property + "\")") + + matchesManuallyEscapedPattern((NotToEscapePattern) value); + } + else if (value instanceof ExecutionProperty) { + return ((ExecutionProperty) value) + .insertValue("response.header(\"" + property + "\")"); + + } + return this.comparisonBuilder.assertThat("response.header(\"" + property + "\")", + value); + } + + private String matchesManuallyEscapedPattern(NotToEscapePattern value) { + return this.comparisonBuilder + .matchesEscaped(value.getServerValue().pattern().replace("\\", "\\\\")); + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Response response = metadata.getContract().getResponse(); + return response.getHeaders() != null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy deleted file mode 100644 index 221f5efe62..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredJUnitMethodBodyBuilder.groovy +++ /dev/null @@ -1,130 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import java.util.regex.Pattern - -import groovy.transform.PackageScope -import groovy.transform.TypeChecked - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.Cookie -import org.springframework.cloud.contract.spec.internal.ExecutionProperty -import org.springframework.cloud.contract.spec.internal.Header -import org.springframework.cloud.contract.spec.internal.NotToEscapePattern -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.util.MapConverter - -/** - * A {@link JUnitMethodBodyBuilder} implementation that uses Rest Assured. - * - * @author Marcin Grzejszczak - * - * @since 1.0.3 - */ -@TypeChecked -@PackageScope -class RestAssuredJUnitMethodBodyBuilder extends JUnitMethodBodyBuilder { - - RestAssuredJUnitMethodBodyBuilder(Contract stubDefinition, ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(stubDefinition, configProperties, classDataForMethod) - } - - @Override - protected void validateResponseCodeBlock(BlockBuilder bb) { - bb.addLine("assertThat(response.statusCode()).isEqualTo($response.status.serverValue);") - } - - @Override - protected void validateResponseHeadersBlock(BlockBuilder bb) { - response.headers?.executeForEachHeader { Header header -> - processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ? - header.serverValue : - MapConverter.getTestSideValues(header.serverValue)) - } - } - - @Override - protected void validateResponseCookiesBlock(BlockBuilder bb) { - response.cookies?.executeForEachCookie { Cookie cookie -> - processCookieElement(bb, cookie.key, cookie.serverValue instanceof NotToEscapePattern ? - cookie.serverValue : - MapConverter.getTestSideValues(cookie.serverValue)) - } - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, Object value) { - return null - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, Pattern value) { - return """assertThat(responseBody).${createBodyComparison(value)}""" - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Object value) { - if (value instanceof NotToEscapePattern) { - blockBuilder.addLine("assertThat(response.header(\"$property\"))." - + - "${createMatchesMethod((value as NotToEscapePattern).serverValue.pattern().replace("\\", "\\\\"))};") - } - else { - // fallback - processHeaderElement(blockBuilder, property, value.toString()) - } - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) { - blockBuilder. - addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(value)}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) { - blockBuilder. - addLine("assertThat(response.header(\"$property\")).isEqualTo(${value});") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern pattern) { - blockBuilder. - addLine("assertThat(response.header(\"$property\")).${createHeaderComparison(pattern)}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder.addLine("${exec.insertValue("response.header(\"$property\")")};") - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) { - blockBuilder.addLine("assertThat(response.getCookie(\"$key\")).isNotNull();") - blockBuilder. - addLine("assertThat(response.getCookie(\"$key\")).${createCookieComparison(pattern)}") - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) { - blockBuilder.addLine("assertThat(response.getCookie(\"$key\")).isNotNull();") - blockBuilder. - addLine("assertThat(response.getCookie(\"$key\")).${createCookieComparison(value)}") - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredStatusCodeThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredStatusCodeThen.java new file mode 100644 index 0000000000..6a61182978 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredStatusCodeThen.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.spec.internal.Response; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class RestAssuredStatusCodeThen implements Then { + + private final BlockBuilder blockBuilder; + + private final ComparisonBuilder comparisonBuilder; + + RestAssuredStatusCodeThen(BlockBuilder blockBuilder, + ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.comparisonBuilder = comparisonBuilder; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + Response response = metadata.getContract().getResponse(); + this.blockBuilder + .addIndented(this.comparisonBuilder.assertThat("response.statusCode()", + response.getStatus().getServerValue())) + .addEndingIfNotPresent(); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return true; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredThen.java new file mode 100644 index 0000000000..d42996d56a --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredThen.java @@ -0,0 +1,61 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.cloud.contract.verifier.config.TestMode; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class RestAssuredThen implements Then, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final List thens = new LinkedList<>(); + + RestAssuredThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData, BodyParser bodyParser, + ComparisonBuilder comparisonBuilder) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.thens.addAll(Arrays.asList( + new RestAssuredStatusCodeThen(this.blockBuilder, comparisonBuilder), + new RestAssuredHeadersThen(this.blockBuilder, comparisonBuilder), + new RestAssuredCookiesThen(this.blockBuilder, comparisonBuilder), + new GenericHttpBodyThen(this.blockBuilder, generatedClassMetaData, + bodyParser, comparisonBuilder))); + } + + @Override + public MethodVisitor apply(SingleContractMetadata singleContractMetadata) { + startBodyBlock(this.blockBuilder, "then:"); + bodyBlock(this.blockBuilder, this.thens, singleContractMetadata); + return this; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return singleContractMetadata.isHttp() + && this.generatedClassMetaData.configProperties + .getTestMode() != TestMode.JAXRSCLIENT; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredVerifier.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredVerifier.java new file mode 100644 index 0000000000..69f404f671 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredVerifier.java @@ -0,0 +1,61 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +interface RestAssuredVerifier { + + Log log = LogFactory.getLog(RestAssuredVerifier.class); + + // TODO: Remove in next major + String REST_ASSURED_2_0_CLASS = "com.jayway.restassured.RestAssured"; + + ClassPresenceChecker checker = new ClassPresenceChecker(); + + @Deprecated + default boolean isRestAssured2Present() { + boolean restAssured2Present = checker.isClassPresent(REST_ASSURED_2_0_CLASS); + if (restAssured2Present) { + log.warn( + "Rest Assured 2 found on the classpath. Please upgrade to the latest version of Rest Assured"); + } + return restAssured2Present; + + } + +} + +class ClassPresenceChecker { + + private static final Log log = LogFactory.getLog(ClassPresenceChecker.class); + + boolean isClassPresent(String className) { + try { + Class.forName(className); + return true; + } + catch (ClassNotFoundException ex) { + if (log.isTraceEnabled()) { + log.trace("[" + className + "] is not present on classpath"); + } + return false; + } + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredWhen.java new file mode 100644 index 0000000000..9385d57387 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/RestAssuredWhen.java @@ -0,0 +1,77 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.LinkedList; +import java.util.List; + +import org.springframework.cloud.contract.verifier.config.TestMode; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class RestAssuredWhen implements When, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final List responseWhens = new LinkedList<>(); + + private final List whens = new LinkedList<>(); + + RestAssuredWhen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData, BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + this.responseWhens.addAll(Arrays.asList( + new MockMvcResponseWhen(blockBuilder, this.generatedClassMetaData), + new SpockMockMvcResponseWhen(blockBuilder, this.generatedClassMetaData), + new ExplicitResponseWhen(blockBuilder, this.generatedClassMetaData), + new WebTestClientResponseWhen(blockBuilder, + this.generatedClassMetaData))); + this.whens.addAll( + Arrays.asList(new MockMvcQueryParamsWhen(this.blockBuilder, bodyParser), + new MockMvcAsyncWhen(this.blockBuilder, + this.generatedClassMetaData), + new MockMvcUrlWhen(this.blockBuilder, bodyParser))); + } + + @Override + public MethodVisitor apply(SingleContractMetadata singleContractMetadata) { + startBodyBlock(this.blockBuilder, "when:"); + addResponseWhenLine(singleContractMetadata); + indentedBodyBlock(this.blockBuilder, this.whens, singleContractMetadata); + this.blockBuilder.addEmptyLine(); + return this; + } + + private void addResponseWhenLine(SingleContractMetadata singleContractMetadata) { + this.responseWhens.stream().filter(when -> when.accept(singleContractMetadata)) + .findFirst() + .orElseThrow(() -> new IllegalStateException( + "No matching request building When implementation for Rest Assured")) + .apply(singleContractMetadata); + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return singleContractMetadata.isHttp() + && this.generatedClassMetaData.configProperties + .getTestMode() != TestMode.JAXRSCLIENT; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleMethodBuilder.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleMethodBuilder.java new file mode 100644 index 0000000000..aed394cd6e --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleMethodBuilder.java @@ -0,0 +1,203 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.List; +import java.util.stream.Collectors; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +/** + * Builds a single method body. Must be executed per contract. + * + * @author Olga Maciaszek-Sharma + * @author Marcin Grzejszczak + * @since 2.2.0 + */ +class SingleMethodBuilder { + + private List methodAnnotations = new LinkedList<>(); + + private List methodMetadata = new LinkedList<>(); + + private List givens = new LinkedList<>(); + + private List whens = new LinkedList<>(); + + private List thens = new LinkedList<>(); + + final GeneratedClassMetaData generatedClassMetaData; + + final BlockBuilder blockBuilder; + + private SingleMethodBuilder(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + static SingleMethodBuilder builder(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + return new SingleMethodBuilder(blockBuilder, generatedClassMetaData); + } + + SingleMethodBuilder methodAnnotation(MethodAnnotations methodAnnotations) { + this.methodAnnotations.add(methodAnnotations); + return this; + } + + MethodAnnotationBuilder methodAnnotation() { + return new MethodAnnotationBuilder(this); + } + + SingleMethodBuilder methodAnnotation(MethodAnnotations... methodAnnotations) { + this.methodAnnotations.addAll(Arrays.asList(methodAnnotations)); + return this; + } + + MethodMetadataBuilder methodMetadata() { + return new MethodMetadataBuilder(this); + } + + SingleMethodBuilder methodMetadata(MethodMetadata... methodMetadata) { + this.methodMetadata.addAll(Arrays.asList(methodMetadata)); + return this; + } + + SingleMethodBuilder restAssured() { + return given( + new JavaRestAssuredGiven(this.blockBuilder, this.generatedClassMetaData)) + .given(new SpockRestAssuredGiven(this.blockBuilder, + this.generatedClassMetaData)) + .when(new JavaRestAssuredWhen(this.blockBuilder, + this.generatedClassMetaData)) + .when(new SpockRestAssuredWhen(this.blockBuilder, + this.generatedClassMetaData)) + .then(new JavaRestAssuredThen(this.blockBuilder, + this.generatedClassMetaData)) + .then(new SpockRestAssuredThen(this.blockBuilder, + this.generatedClassMetaData)); + } + + SingleMethodBuilder jaxRs() { + return given(new JaxRsGiven(this.generatedClassMetaData)) + .when(new JavaJaxRsWhen(this.blockBuilder, this.generatedClassMetaData)) + .when(new SpockJaxRsWhen(this.blockBuilder, this.generatedClassMetaData)) + .then(new JavaJaxRsThen(this.blockBuilder, this.generatedClassMetaData)) + .then(new SpockJaxRsThen(this.blockBuilder, this.generatedClassMetaData)); + } + + SingleMethodBuilder messaging() { + // @formatter:off + return given(new JavaMessagingGiven(this.blockBuilder, this.generatedClassMetaData)) + .given(new SpockMessagingGiven(this.blockBuilder, this.generatedClassMetaData)) + .when(new MessagingWhen(this.blockBuilder, this.generatedClassMetaData)) + .then(new JavaMessagingWithBodyThen(this.blockBuilder, + this.generatedClassMetaData)) + .then(new SpockMessagingWithBodyThen(this.blockBuilder, + this.generatedClassMetaData)) + .then(new SpockMessagingEmptyThen(this.blockBuilder, + this.generatedClassMetaData)); + // @formatter:on + } + + SingleMethodBuilder given(Given... given) { + this.givens.addAll(Arrays.asList(given)); + return this; + } + + SingleMethodBuilder when(When... when) { + this.whens.addAll(Arrays.asList(when)); + return this; + } + + SingleMethodBuilder then(Then... then) { + this.thens.addAll(Arrays.asList(then)); + return this; + } + + /** + * Mutates the {@link BlockBuilder} to generate a methodBuilder + * @return block builder with contents of a single methodBuilder + */ + BlockBuilder build() { + MethodMetadata methodMetadatum = pickMetadatum(); + // \n + this.blockBuilder.addEmptyLine(); + this.generatedClassMetaData.toSingleContractMetadata().forEach(metaData -> { + // @Test + if (visit(this.methodAnnotations, metaData, false)) { + this.blockBuilder.addEmptyLine(); + } + // @formatter:off + // public void validate_foo() + this.blockBuilder.append(methodMetadatum::modifier) + .appendWithSpace(methodMetadatum::returnType) + .appendWithSpace(() -> methodMetadatum.name(metaData)) + .append("() throws Exception "); + // (space) { + this.blockBuilder.inBraces(() -> { + // (indent) given + if (visit(this.givens, metaData)) { + this.blockBuilder.addEmptyLine(); + } + // (indent) when + visit(this.whens, metaData); + this.blockBuilder.addEmptyLine(); + // (indent) then + visit(this.thens, metaData); + }); + this.blockBuilder.addEmptyLine(); + // } + }); + // @formatter:on + return this.blockBuilder; + } + + private MethodMetadata pickMetadatum() { + return this.methodMetadata.stream().filter(Acceptor::accept).findFirst() + .orElseThrow(() -> new IllegalStateException( + "No matching method metadata found")); + } + + private boolean visit(List list, + SingleContractMetadata metaData) { + return visit(list, metaData, true); + } + + private boolean visit(List list, + SingleContractMetadata metaData, boolean addLineEnding) { + List visitors = list.stream() + .filter(o -> o.accept(metaData)).collect(Collectors.toList()); + Iterator iterator = visitors.iterator(); + while (iterator.hasNext()) { + MethodVisitor visitor = iterator.next(); + visitor.apply(metaData); + if (addLineEnding) { + this.blockBuilder.addEndingIfNotPresent(); + } + if (iterator.hasNext()) { + this.blockBuilder.addEmptyLine(); + } + } + return !visitors.isEmpty(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.java similarity index 61% rename from spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy rename to spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.java index b0808b4bbe..eb8280924c 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SingleTestGenerator.java @@ -14,70 +14,78 @@ * limitations under the License. */ -package org.springframework.cloud.contract.verifier.builder +package org.springframework.cloud.contract.verifier.builder; +import java.nio.file.Path; +import java.util.Collection; -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.file.ContractMetadata +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties; +import org.springframework.cloud.contract.verifier.file.ContractMetadata; /** * Builds a single test. * * @since 1.1.0 */ -trait SingleTestGenerator { +public interface SingleTestGenerator { /** - * Creates contents of a single test class in which all test scenarios from - * the contract metadata should be placed. - * + * Creates contents of a single test class in which all test scenarios from the + * contract metadata should be placed. * @param properties - properties passed to the plugin * @param listOfFiles - list of parsed contracts with additional metadata * @param className - the name of the generated test class - * @param classPackage - the name of the package in which the test class should be stored + * @param classPackage - the name of the package in which the test class should be + * stored * @param includedDirectoryRelativePath - relative path to the included directory * @return contents of a single test class * @deprecated use{@link SingleTestGenerator#buildClass(ContractVerifierConfigProperties, Collection, String, GeneratedClassData)} */ @Deprecated - abstract String buildClass(ContractVerifierConfigProperties properties, - Collection listOfFiles, String className, String classPackage, String includedDirectoryRelativePath) + String buildClass(ContractVerifierConfigProperties properties, + Collection listOfFiles, String className, + String classPackage, String includedDirectoryRelativePath); /** - * Creates contents of a single test class in which all test scenarios from - * the contract metadata should be placed. - * + * Creates contents of a single test class in which all test scenarios from the + * contract metadata should be placed. * @param properties - properties passed to the plugin * @param listOfFiles - list of parsed contracts with additional metadata * @param generatedClassData - information about the generated class * @param includedDirectoryRelativePath - relative path to the included directory * @return contents of a single test class */ - String buildClass(ContractVerifierConfigProperties properties, - Collection listOfFiles, String includedDirectoryRelativePath, GeneratedClassData generatedClassData) { - String className = generatedClassData.className - String classPackage = generatedClassData.classPackage - String path = includedDirectoryRelativePath - return buildClass(properties, listOfFiles, className, classPackage, path) + default String buildClass(ContractVerifierConfigProperties properties, + Collection listOfFiles, + String includedDirectoryRelativePath, GeneratedClassData generatedClassData) { + String className = generatedClassData.className; + String classPackage = generatedClassData.classPackage; + String path = includedDirectoryRelativePath; + return buildClass(properties, listOfFiles, className, classPackage, path); } /** - * Extension that should be appended to the generated test class. E.g. {@code .java} or {@code .php} - * + * Extension that should be appended to the generated test class. E.g. {@code .java} + * or {@code .php} * @param properties - properties passed to the plugin */ - abstract String fileExtension(ContractVerifierConfigProperties properties) + String fileExtension(ContractVerifierConfigProperties properties); - static class GeneratedClassData { - public final String className - public final String classPackage - public final java.nio.file.Path testClassPath + class GeneratedClassData { - GeneratedClassData(String className, String classPackage, - java.nio.file.Path testClassPath) { - this.className = className - this.classPackage = classPackage - this.testClassPath = testClassPath + public final String className; + + public final String classPackage; + + public final Path testClassPath; + + public GeneratedClassData(String className, String classPackage, + Path testClassPath) { + this.className = className; + this.classPackage = classPackage; + this.testClassPath = testClassPath; } + } + } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockIgnoreImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockIgnoreImports.java new file mode 100644 index 0000000000..aed522d5ef --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockIgnoreImports.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockIgnoreImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + SpockIgnoreImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + this.blockBuilder.addLineWithEnding("import spock.lang.Ignore"); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK + && this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(metadata -> metadata.isIgnored() + || metadata.getConvertedContractWithMetadata().stream() + .anyMatch(SingleContractMetadata::isIgnored)); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockIgnoreMethodAnnotation.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockIgnoreMethodAnnotation.java new file mode 100644 index 0000000000..59d260e244 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockIgnoreMethodAnnotation.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockIgnoreMethodAnnotation implements MethodAnnotations { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] ANNOTATIONS = { "@Ignore" }; + + SpockIgnoreMethodAnnotation(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public MethodVisitor apply( + SingleContractMetadata singleContractMetadata) { + Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented); + return this; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK + && this.generatedClassMetaData.isAnyIgnored(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockImports.java new file mode 100644 index 0000000000..245740c328 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockImports.java @@ -0,0 +1,50 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; + +class SpockImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "spock.lang.Specification" }; + + SpockImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsBodyParser.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsBodyParser.java new file mode 100644 index 0000000000..f041836539 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsBodyParser.java @@ -0,0 +1,40 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.template.HandlebarsTemplateProcessor; + +interface SpockJaxRsBodyParser extends JaxRsBodyParser, GroovyBodyParser { + + SpockJaxRsBodyParser INSTANCE = HandlebarsTemplateProcessor::new; + + @Override + default String readEntity() { + return "response.readEntity(String)"; + } + + @Override + default String responseAsString() { + return "responseAsString"; + } + + @Override + default String byteArrayString() { + return "response.readEntity(byte[])"; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsThen.java new file mode 100644 index 0000000000..e73dc14e2b --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsThen.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockJaxRsThen extends JaxRsThen { + + private final GeneratedClassMetaData metaData; + + SpockJaxRsThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, SpockJaxRsBodyParser.INSTANCE, + GroovyComparisonBuilder.JAXRS_HTTP_INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsWhen.java new file mode 100644 index 0000000000..6e52b53c62 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockJaxRsWhen.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockJaxRsWhen extends JaxRsWhen { + + private final GeneratedClassMetaData metaData; + + SpockJaxRsWhen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, SpockJaxRsBodyParser.INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingBodyParser.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingBodyParser.java new file mode 100644 index 0000000000..16d3c72c10 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingBodyParser.java @@ -0,0 +1,25 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.template.HandlebarsTemplateProcessor; + +interface SpockMessagingBodyParser extends MessagingBodyParser, GroovyBodyParser { + + BodyParser INSTANCE = (SpockMessagingBodyParser) HandlebarsTemplateProcessor::new; + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingEmptyThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingEmptyThen.java new file mode 100644 index 0000000000..27496f03a5 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingEmptyThen.java @@ -0,0 +1,49 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockMessagingEmptyThen implements Then, BodyMethodVisitor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + SpockMessagingEmptyThen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + startBodyBlock(this.blockBuilder, "then:"); + this.blockBuilder.addLineWithEnding("noExceptionThrown()"); + endBodyBlock(this.blockBuilder); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return metadata.isMessaging() + && this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK + && metadata.getContract().getOutputMessage() == null; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingGiven.java new file mode 100644 index 0000000000..1af5f88bb9 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingGiven.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockMessagingGiven extends MessagingGiven { + + private final GeneratedClassMetaData generatedClassMetaData; + + SpockMessagingGiven(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, SpockMessagingBodyParser.INSTANCE); + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return super.accept(metadata) && this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy deleted file mode 100644 index 4965ac7563..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingMethodBodyBuilder.groovy +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import java.util.regex.Pattern - -import groovy.json.StringEscapeUtils -import groovy.transform.PackageScope -import groovy.transform.TypeChecked - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.Cookie -import org.springframework.cloud.contract.spec.internal.ExecutionProperty -import org.springframework.cloud.contract.spec.internal.FromFileProperty -import org.springframework.cloud.contract.spec.internal.Header -import org.springframework.cloud.contract.spec.internal.Input -import org.springframework.cloud.contract.spec.internal.NamedProperty -import org.springframework.cloud.contract.spec.internal.NotToEscapePattern -import org.springframework.cloud.contract.spec.internal.RegexProperty -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.util.MapConverter - -import static org.apache.commons.text.StringEscapeUtils.escapeJava - -/** - * @author Jakub Kubrynski, codearte.io - * @author Tim Ysewyn - */ -@PackageScope -@TypeChecked -class SpockMessagingMethodBodyBuilder extends MessagingMethodBodyBuilder { - - SpockMessagingMethodBodyBuilder(Contract stubDefinition, - ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(stubDefinition, configProperties, classDataForMethod) - } - - @Override - protected String getInputString(Input request) { - if (request.triggeredBy) { - return request.triggeredBy.executionCommand - } - return "contractVerifierMessaging.send(inputMessage, '${request.messageFrom.serverValue}')" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, String value) { - return "responseBody$property == \"${value}\"" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, Pattern value) { - return "" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, ExecutionProperty value) { - return "" - } - - @Override - protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder.addLine("${exec.insertValue("parsedJson.read('\\\$$property')")}") - } - - @Override - protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) { - processBodyElement(blockBuilder, property, property + "." + entry.key, entry.value) - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder. - addLine("${exec.insertValue("response.getHeader(\'$property\')?.toString()")}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, String value) { - blockBuilder. - addLine("response.getHeader('$property')?.toString() ${convertHeaderComparison(value)}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Number value) { - blockBuilder.addLine("response.getHeader('$property') == ${value}") - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, Pattern value) { - blockBuilder. - addLine("response.getHeader('$property')?.toString() ${convertHeaderComparison(value)}") - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, Pattern pattern) { - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, String value) { - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, GString value) { - } - - @Override - protected void validateResponseCodeBlock(BlockBuilder bb) { - if (outputMessage) { - bb.addLine("""ContractVerifierMessage response = contractVerifierMessaging.receive(${ - sentToValue(outputMessage.sentTo.serverValue) - })""") - bb.addLine("""assert response != null""") - } - else { - bb.addLine('noExceptionThrown()') - } - } - - private String sentToValue(Object sentTo) { - if (sentTo instanceof ExecutionProperty) { - return ((ExecutionProperty) sentTo).executionCommand - } - return "'" + sentTo.toString() + "'" - } - - @Override - protected void validateResponseHeadersBlock(BlockBuilder bb) { - outputMessage.headers?.executeForEachHeader { Header header -> - processHeaderElement(bb, header.name, header.serverValue instanceof NotToEscapePattern ? - header.serverValue : - MapConverter.getTestSideValues(header.serverValue)) - } - } - - @Override - protected void validateResponseCookiesBlock(BlockBuilder bb) { - } - - @Override - protected String getResponseAsString() { - return 'contractVerifierObjectMapper.writeValueAsString(response.payload)' - } - - @Override - protected String addCommentSignIfRequired(String baseString) { - return baseString - } - - @Override - protected boolean shouldCommentOutBDDBlocks() { - return false - } - - @Override - protected BlockBuilder addColonIfRequired(BlockBuilder blockBuilder) { - return blockBuilder - } - - @Override - protected Optional lineSuffix() { - return Optional.empty() - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, Object value) { - return "" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) { - if (value.isByte()) { - return "response.payloadAsByteArray == " + - readBytesFromFileString(value, CommunicationType.RESPONSE) - } - return getResponseBodyPropertyComparisonString(property, value.asString()) - } - - @Override - protected String getPropertyInListString(String property, Integer listIndex) { - return "$property[$listIndex]" ?: '' - } - - @Override - protected String convertUnicodeEscapesIfRequired(String json) { - return StringEscapeUtils.unescapeJavaScript(json) - } - - @Override - protected String getSimpleResponseBodyString(String responseString) { - return "def responseBody = ($responseString)" - } - - @Override - protected String getInputString() { - String request = 'ContractVerifierMessage inputMessage = contractVerifierMessaging.create(' - if (inputMessage.messageBody) { - request = "${request}${getBodyAsString()}\n " - } - if (inputMessage.messageHeaders) { - request = "${request},[\n" - } - def headers = [] - inputMessage.messageHeaders?.executeForEachHeader { Header header -> - headers << " ${getHeaderString(header)}" - } - request = "${request}${headers.join(',\n')}" - if (inputMessage.messageHeaders) { - request = "${request}\n ]" - } - return "${request})" - } - - @Override - protected String indentBody(String text) { - return "\n ${text}\n" - } - - @Override - protected String quotes() { - return "'''" - } - - @Override - protected String getHeaderString(Header header) { - return "${getTestSideValue(header.name)}: ${getTestSideValue(header.serverValue)}" - } - - @Override - protected String getCookieString(Cookie cookie) { - return '' - } - - @Override - protected String getBodyString(Object body) { - return '' - } - - @Override - protected String getMultipartFileParameterContent(String propertyName, NamedProperty propertyValue) { - return '' - } - - @Override - protected String getParameterString(Map.Entry parameter) { - return '' - } - - protected String convertHeaderComparison(String headerValue) { - return " == '$headerValue'" - } - - protected String convertHeaderComparison(RegexProperty headerValue) { - return convertHeaderComparison(headerValue.pattern) - } - - protected String convertHeaderComparison(Pattern headerValue) { - String converted = - escapeJava(convertUnicodeEscapesIfRequired(headerValue.pattern())) - return "==~ java.util.regex.Pattern.compile('${converted}')" - } - - // #273 - should escape $ for Groovy since it will try to make it a GString - @Override - protected String postProcessJsonPathCall(String method) { - if (templateProcessor.containsTemplateEntry(method)) { - return method - } - return method.replace('$', '\\$') - } - -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingWithBodyThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingWithBodyThen.java new file mode 100644 index 0000000000..ff95aac120 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMessagingWithBodyThen.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockMessagingWithBodyThen extends MessagingWithBodyThen { + + private final GeneratedClassMetaData metaData; + + SpockMessagingWithBodyThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, + GroovyComparisonBuilder.SPOCK_MESSAGING_INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodMetadata.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodMetadata.java new file mode 100644 index 0000000000..64170bee26 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodMetadata.java @@ -0,0 +1,57 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockMethodMetadata implements MethodMetadata { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData metaData; + + private final NameProvider nameProvider = new NameProvider(); + + SpockMethodMetadata(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.metaData = metaData; + } + + @Override + public MethodMetadata name(SingleContractMetadata metaData) { + this.blockBuilder.addAtTheEnd(this.nameProvider.methodName(metaData)); + return this; + } + + @Override + public MethodMetadata modifier() { + return this; + } + + @Override + public MethodMetadata returnType() { + this.blockBuilder.addIndented("def"); + return this; + } + + @Override + public boolean accept() { + return this.metaData.configProperties.getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy deleted file mode 100644 index 72bc543e1f..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMethodRequestProcessingBodyBuilder.groovy +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import java.util.regex.Pattern - -import groovy.json.StringEscapeUtils -import groovy.transform.PackageScope -import groovy.transform.TypeChecked - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.Cookie -import org.springframework.cloud.contract.spec.internal.ExecutionProperty -import org.springframework.cloud.contract.spec.internal.FromFileProperty -import org.springframework.cloud.contract.spec.internal.Header -import org.springframework.cloud.contract.spec.internal.NamedProperty -import org.springframework.cloud.contract.spec.internal.RegexProperty -import org.springframework.cloud.contract.spec.internal.Request -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties -import org.springframework.cloud.contract.verifier.util.ContentUtils -import org.springframework.cloud.contract.verifier.util.RegexpBuilders - -import static org.apache.commons.text.StringEscapeUtils.escapeJava -import static org.springframework.cloud.contract.verifier.util.ContentUtils.getGroovyMultipartFileParameterContent - -/** - * A {@link RequestProcessingMethodBodyBuilder} implementation that uses Spock - * - * @author Jakub Kubrynski, codearte.io - * - * @since 1.0.0 - */ -@PackageScope -@TypeChecked -abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessingMethodBodyBuilder { - - SpockMethodRequestProcessingBodyBuilder(Contract stubDefinition, - ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(stubDefinition, configProperties, classDataForMethod) - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, String value) { - return "responseBody$property == \"${value}\"" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, Object value) { - return getResponseBodyPropertyComparisonString(property, value as String) - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, Pattern value) { - return "responseBody$property ${createBodyComparison(value)}" - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, ExecutionProperty value) { - return value.insertValue("responseBody${property}") - } - - @Override - protected void processBodyElement(BlockBuilder blockBuilder, String property, ExecutionProperty exec) { - blockBuilder.addLine("${exec.insertValue("parsedJson.read('''\$$property''')")}") - } - - @Override - protected void processBodyElement(BlockBuilder blockBuilder, String property, Map.Entry entry) { - processBodyElement(blockBuilder, property, property + "." + entry.key, entry.value) - } - - @Override - protected String addCommentSignIfRequired(String baseString) { - return baseString - } - - @Override - protected boolean shouldCommentOutBDDBlocks() { - return false - } - - @Override - protected BlockBuilder addColonIfRequired(BlockBuilder blockBuilder) { - return blockBuilder - } - - @Override - protected Optional lineSuffix() { - return Optional.empty() - } - - @Override - protected String getPropertyInListString(String property, Integer listIndex) { - "$property[$listIndex]" ?: '' - } - - @Override - protected String convertUnicodeEscapesIfRequired(String json) { - return StringEscapeUtils.unescapeJavaScript(json) - } - - @Override - protected String getResponseBodyPropertyComparisonString(String property, FromFileProperty value) { - if (value.isByte()) { - return "response.body.asByteArray() == " + - readBytesFromFileString(value, CommunicationType.RESPONSE) - } - return getResponseBodyPropertyComparisonString(property, value.asString()) - } - - @Override - protected String getSimpleResponseBodyString(String responseString) { - return "def responseBody = ($responseString)" - } - - @Override - protected String getInputString(Request request) { - return 'def response = given().spec(request)' - } - - @Override - protected String getInputString() { - return 'def request = given()' - } - - @Override - protected String getHeaderString(Header header) { - return ".header(${getTestSideForNonBodyValue(header.name)}, ${getTestSideForNonBodyValue(header.serverValue)})" - } - - @Override - protected String getCookieString(Cookie cookie) { - return ".cookie(${getTestSideForNonBodyValue(cookie.key)}, ${getTestSideForNonBodyValue(cookie.serverValue)})" - } - - @Override - protected String getBodyString(Object body) { - String value - if (body instanceof ExecutionProperty) { - value = body.toString() - } - else if (body instanceof FromFileProperty) { - FromFileProperty fileProperty = (FromFileProperty) body - value = fileProperty.isByte() ? - readBytesFromFileString(fileProperty, CommunicationType.REQUEST) : - readStringFromFileString(fileProperty, CommunicationType.REQUEST) - } - else { - String escaped = escapeRequestSpecialChars(body.toString()) - value = "'''$escaped'''" - } - return ".body($value)" - } - - @Override - protected String getMultipartFileParameterContent(String propertyName, NamedProperty propertyValue) { - return getGroovyMultipartFileParameterContent(propertyName, propertyValue, { FromFileProperty fileProp -> - readBytesFromFileString(fileProp, CommunicationType.REQUEST) - }) - } - - @Override - protected String getParameterString(Map.Entry parameter) { - return ".param('$parameter.key', '$parameter.value')" - } - - @Override - protected void processHeaderElement(BlockBuilder blockBuilder, String property, GString value) { - String gstringValue = ContentUtils. - extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString() - processHeaderElement(blockBuilder, property, gstringValue) - } - - @Override - protected void processCookieElement(BlockBuilder blockBuilder, String key, GString value) { - String gStringValue = ContentUtils. - extractValueForGString(value, ContentUtils.GET_TEST_SIDE).toString() - processCookieElement(blockBuilder, key, gStringValue) - } - - protected String convertHeaderComparison(String headerValue) { - return " == '$headerValue'" - } - - protected String convertHeaderComparison(Pattern headerValue) { - return patternComparisonWithMatchesCheck(escapeJava(headerValue.pattern())) - } - - protected String convertHeaderComparison(RegexProperty headerValue) { - return patternComparisonWithMatchesCheck(escapeJava(headerValue.pattern.pattern())) - } - - protected String convertCookieComparison(String cookieValue) { - return "== '$cookieValue'" - } - - protected String createBodyComparison(RegexProperty bodyValue) { - return createBodyComparison(bodyValue.pattern) - } - - protected String createBodyComparison(Pattern bodyValue) { - String patternAsString = bodyValue.pattern() - return patternComparison(RegexpBuilders. - buildGStringRegexpForTestSide(patternAsString)) + ";" - } - - protected String convertCookieComparison(Pattern cookieValue) { - return patternComparisonWithMatchesCheck(convertUnicodeEscapesIfRequired(cookieValue.pattern())) - } - - protected String patternComparison(Pattern pattern) { - return patternComparison(pattern.toString()) - } - - protected String patternComparison(String pattern) { - String converted = escapeJava(convertUnicodeEscapesIfRequired(pattern)) - return patternComparisonWithMatchesCheck(converted) - } - - private String patternComparisonWithMatchesCheck(String converted) { - return "==~ java.util.regex.Pattern.compile('${converted}')" - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcMultipartGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcMultipartGiven.java new file mode 100644 index 0000000000..81803eff67 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcMultipartGiven.java @@ -0,0 +1,88 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Map; + +import org.springframework.cloud.contract.spec.internal.NamedProperty; +import org.springframework.cloud.contract.spec.internal.Request; +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; +import org.springframework.cloud.contract.verifier.util.ContentUtils; + +class SpockMockMvcMultipartGiven implements Given { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final BodyReader bodyReader; + + private final BodyParser bodyParser; + + SpockMockMvcMultipartGiven(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData, BodyParser bodyParser) { + this.blockBuilder = blockBuilder; + this.bodyReader = new BodyReader(generatedClassMetaData); + this.bodyParser = bodyParser; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + getMultipartParameters(metadata).entrySet().forEach(entry -> this.blockBuilder + .addLine(getMultipartParameterLine(metadata, entry))); + return this; + } + + private String getMultipartParameterLine(SingleContractMetadata metadata, + Map.Entry parameter) { + if (parameter.getValue() instanceof NamedProperty) { + return ".multiPart(" + getMultipartFileParameterContent(metadata, + parameter.getKey(), (NamedProperty) parameter.getValue()) + ")"; + } + return getParameterString(parameter); + } + + @SuppressWarnings("unchecked") + private Map getMultipartParameters(SingleContractMetadata metadata) { + return (Map) metadata.getContract().getRequest().getMultipart() + .getServerValue(); + } + + private String getMultipartFileParameterContent(SingleContractMetadata metadata, + String propertyName, NamedProperty propertyValue) { + return ContentUtils.getGroovyMultipartFileParameterContent(propertyName, + propertyValue, + fileProp -> this.bodyReader.readBytesFromFileString(metadata, fileProp, + CommunicationType.REQUEST)); + } + + private String getParameterString(Map.Entry parameter) { + return ".param(" + this.bodyParser.quotedShortText(parameter.getKey()) + ", " + + this.bodyParser.quotedShortText(parameter.getValue()) + ")"; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Request request = metadata.getContract().getRequest(); + return request != null && request.getMultipart() != null + && this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcRequestGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcRequestGiven.java new file mode 100644 index 0000000000..3c0f9ac432 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcRequestGiven.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockMockMvcRequestGiven implements Given, MockMvcAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + SpockMockMvcRequestGiven(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder.addIndented("def request = given()"); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return acceptType(this.generatedClassMetaData, metadata) + && this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcResponseWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcResponseWhen.java new file mode 100644 index 0000000000..10d9f335ac --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockMockMvcResponseWhen.java @@ -0,0 +1,46 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockMockMvcResponseWhen implements When, MockMvcAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + SpockMockMvcResponseWhen(BlockBuilder blockBuilder, GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder.addIndented("def response = given().spec(request)"); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return acceptType(this.generatedClassMetaData, metadata) + && this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockOrderClassAnnotation.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockOrderClassAnnotation.java new file mode 100644 index 0000000000..386d0b06dc --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockOrderClassAnnotation.java @@ -0,0 +1,51 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; + +class SpockOrderClassAnnotation implements ClassAnnotation { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] ANNOTATIONS = { "@Stepwise" }; + + SpockOrderClassAnnotation(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public ClassAnnotation call() { + Arrays.stream(ANNOTATIONS).forEach(this.blockBuilder::addIndented); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK + && this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(meta -> meta.getOrder() != null); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockOrderImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockOrderImports.java new file mode 100644 index 0000000000..d56c929fd2 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockOrderImports.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestFramework; + +class SpockOrderImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "spock.lang.Stepwise" }; + + SpockOrderImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestFramework() == TestFramework.SPOCK + && this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(meta -> meta.getOrder() != null); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredBodyParser.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredBodyParser.java new file mode 100644 index 0000000000..43e6c04a62 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredBodyParser.java @@ -0,0 +1,35 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.template.HandlebarsTemplateProcessor; + +interface SpockRestAssuredBodyParser extends RestAssuredBodyParser, GroovyBodyParser { + + BodyParser INSTANCE = (SpockRestAssuredBodyParser) HandlebarsTemplateProcessor::new; + + @Override + default String responseAsString() { + return "response.body.asString()"; + } + + @Override + default String byteArrayString() { + return "response.body.asByteArray()"; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredGiven.java new file mode 100644 index 0000000000..b66357b4dc --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredGiven.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockRestAssuredGiven extends RestAssuredGiven { + + private final GeneratedClassMetaData metaData; + + SpockRestAssuredGiven(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, SpockRestAssuredBodyParser.INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredThen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredThen.java new file mode 100644 index 0000000000..6f6eb60c74 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredThen.java @@ -0,0 +1,39 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockRestAssuredThen extends RestAssuredThen { + + private final GeneratedClassMetaData metaData; + + SpockRestAssuredThen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, SpockRestAssuredBodyParser.INSTANCE, + GroovyComparisonBuilder.SPOCK_HTTP_INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredWhen.java new file mode 100644 index 0000000000..3da798816f --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/SpockRestAssuredWhen.java @@ -0,0 +1,38 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestFramework; +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class SpockRestAssuredWhen extends RestAssuredWhen { + + private final GeneratedClassMetaData metaData; + + SpockRestAssuredWhen(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + super(blockBuilder, generatedClassMetaData, RestAssuredBodyParser.INSTANCE); + this.metaData = generatedClassMetaData; + } + + @Override + public boolean accept(SingleContractMetadata singleContractMetadata) { + return super.accept(singleContractMetadata) && this.metaData.configProperties + .getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Then.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Then.java new file mode 100644 index 0000000000..66f540318a --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Then.java @@ -0,0 +1,21 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface Then extends MethodVisitor { + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Visitor.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Visitor.java new file mode 100644 index 0000000000..56cb0f685b --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/Visitor.java @@ -0,0 +1,21 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface Visitor extends Acceptor, OurCallable { + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientAcceptor.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientAcceptor.java new file mode 100644 index 0000000000..34195c96dc --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientAcceptor.java @@ -0,0 +1,28 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.config.TestMode; + +interface WebTestClientAcceptor { + + default boolean acceptType(GeneratedClassMetaData generatedClassMetaData) { + return generatedClassMetaData.configProperties + .getTestMode() == TestMode.WEBTESTCLIENT; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientJUnitMethodBodyBuilder.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientJUnitMethodBodyBuilder.groovy deleted file mode 100644 index 37a9551206..0000000000 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientJUnitMethodBodyBuilder.groovy +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright 2013-2019 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.springframework.cloud.contract.verifier.builder - -import groovy.transform.CompileStatic -import groovy.transform.PackageScope - -import org.springframework.cloud.contract.spec.Contract -import org.springframework.cloud.contract.spec.internal.Url -import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties - -/** - * A {@link JUnitMethodBodyBuilder} implementation that uses WebTestClient to send requests. - * - * @author Olga Maciaszek-Sharma - * - * @since 2.1.0 - */ -@CompileStatic -@PackageScope -class WebTestClientJUnitMethodBodyBuilder extends RestAssuredJUnitMethodBodyBuilder { - - WebTestClientJUnitMethodBodyBuilder(Contract stubDefinition, - ContractVerifierConfigProperties configProperties, - GeneratedClassDataForMethod classDataForMethod) { - super(stubDefinition, configProperties, classDataForMethod) - } - - @Override - protected String returnedResponseType() { - return 'WebTestClientResponse' - } - - @Override - protected String returnedRequestType() { - return 'WebTestClientRequestSpecification' - } - - @Override - protected void when(BlockBuilder bb) { - bb.addLine(getInputString(request)) - bb.indent() - - Url url = getUrl(request) - addQueryParameters(url, bb) - addUrl(url, bb) - addColonIfRequired(bb) - bb.unindent() - } -} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRequestGiven.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRequestGiven.java new file mode 100644 index 0000000000..3dac20b99c --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRequestGiven.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class WebTestClientRequestGiven implements Given, WebTestClientAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + WebTestClientRequestGiven(BlockBuilder blockBuilder, + GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder + .addIndented("WebTestClientRequestSpecification request = given()"); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return acceptType(this.generatedClassMetaData); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientResponseWhen.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientResponseWhen.java new file mode 100644 index 0000000000..305d39b9b4 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientResponseWhen.java @@ -0,0 +1,45 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class WebTestClientResponseWhen implements When, WebTestClientAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + WebTestClientResponseWhen(BlockBuilder blockBuilder, + GeneratedClassMetaData metaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = metaData; + } + + @Override + public MethodVisitor apply(SingleContractMetadata metadata) { + this.blockBuilder + .addIndented("WebTestClientResponse response = given().spec(request)"); + return this; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + return acceptType(this.generatedClassMetaData); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRestAssured3StaticImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRestAssured3StaticImports.java new file mode 100644 index 0000000000..e979e2e04a --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRestAssured3StaticImports.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestMode; + +class WebTestClientRestAssured3StaticImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { + "io.restassured.module.webtestclient.RestAssuredWebTestClient.*" }; + + WebTestClientRestAssured3StaticImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import static " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestMode() == TestMode.WEBTESTCLIENT + && this.generatedClassMetaData.isAnyHttp(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRestAssuredImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRestAssuredImports.java new file mode 100644 index 0000000000..0293e15394 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/WebTestClientRestAssuredImports.java @@ -0,0 +1,58 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.config.TestMode; + +class WebTestClientRestAssuredImports implements Imports, RestAssuredVerifier { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] REST_ASSURED_2_IMPORTS = { + "com.jayway.restassured.module.webtestclient.specification.WebTestClientRequestSpecification", + "com.jayway.restassured.module.webtestclient.response.WebTestClientResponse" }; + + private static final String[] REST_ASSURED_3_IMPORTS = { + "io.restassured.module.webtestclient.specification.WebTestClientRequestSpecification", + "io.restassured.module.webtestclient.response.WebTestClientResponse" }; + + WebTestClientRestAssuredImports(BlockBuilder blockBuilder, + GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream( + isRestAssured2Present() ? REST_ASSURED_2_IMPORTS : REST_ASSURED_3_IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.configProperties + .getTestMode() == TestMode.WEBTESTCLIENT + && this.generatedClassMetaData.isAnyHttp(); + } + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/When.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/When.java new file mode 100644 index 0000000000..6cc630a225 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/When.java @@ -0,0 +1,21 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +interface When extends MethodVisitor { + +} diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/XmlImports.java b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/XmlImports.java new file mode 100644 index 0000000000..65f2cdb0cd --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/builder/XmlImports.java @@ -0,0 +1,52 @@ +/* + * Copyright 2013-2019 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.cloud.contract.verifier.builder; + +import java.util.Arrays; + +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata; + +class XmlImports implements Imports { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private static final String[] IMPORTS = { "javax.xml.parsers.DocumentBuilder", + "javax.xml.parsers.DocumentBuilderFactory", "org.w3c.dom.Document", + "org.xml.sax.InputSource", "java.io.StringReader" }; + + XmlImports(BlockBuilder blockBuilder, GeneratedClassMetaData generatedClassMetaData) { + this.blockBuilder = blockBuilder; + this.generatedClassMetaData = generatedClassMetaData; + } + + @Override + public Imports call() { + Arrays.stream(IMPORTS) + .forEach(s -> this.blockBuilder.addLineWithEnding("import " + s)); + return this; + } + + @Override + public boolean accept() { + return this.generatedClassMetaData.listOfFiles.stream() + .anyMatch(metadata -> metadata.getConvertedContractWithMetadata().stream() + .anyMatch(SingleContractMetadata::isXml)); + } + +} 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 index 3ea91da62c..2da3931588 100644 --- 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 @@ -31,8 +31,10 @@ import static org.springframework.cloud.contract.verifier.config.TestFramework.S * @author Olga Maciaszek-Sharma * * @since 2.1.0 + * @deprecated */ @CompileStatic +@Deprecated class BaseImportProvider { private static final ImportDefinitions GENERAL_IMPORTS = new ImportDefinitions([], [ 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 index cb5322ff94..4fe63d76cd 100644 --- 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 @@ -35,6 +35,7 @@ import static org.springframework.cloud.contract.verifier.config.TestMode.WEBTES * * @since 2.1.0 */ +@Deprecated class HttpImportProvider { private final Map TEST_MODE_SPECIFIC_IMPORTS = [ 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 index 675868f467..92dbb7efca 100644 --- 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 @@ -26,6 +26,7 @@ import groovy.transform.PackageScope */ @CompileStatic @PackageScope +@Deprecated class ImportDefinitions { final List imports 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 index 6f15131e58..76851b42af 100644 --- 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 @@ -26,6 +26,7 @@ import groovy.transform.CompileStatic * @since 2.1.0 */ @CompileStatic +@Deprecated class MessagingImportProvider { /** 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 cb002725e5..488e088c84 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,6 +16,8 @@ package org.springframework.cloud.contract.verifier.config +import groovy.transform.CompileStatic + 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 @@ -30,6 +32,7 @@ import org.springframework.cloud.contract.verifier.config.framework.TestFramewor * * @since 1.0.0 */ +@CompileStatic enum TestFramework { SPOCK(new SpockDefinition()), @@ -37,7 +40,6 @@ enum TestFramework { JUNIT5(new JUnit5Definition()), CUSTOM(new CustomDefinition()) - @Delegate private final TestFrameworkDefinition testFrameworkDefinition @@ -117,4 +119,48 @@ enum TestFramework { } } } + + String getClassModifier() { + return this.testFrameworkDefinition.classModifier + } + + String getMethodModifier() { + return this.testFrameworkDefinition.methodModifier + } + + String getLineSuffix() { + return this.testFrameworkDefinition.lineSuffix + } + + String getClassExtension() { + return this.testFrameworkDefinition.classExtension + } + + String getClassNameSuffix() { + return this.testFrameworkDefinition.classNameSuffix + } + + String getIgnoreClass() { + return this.testFrameworkDefinition.ignoreClass + } + + List getOrderAnnotationImports() { + return this.testFrameworkDefinition.orderAnnotationImports + } + + String getOrderAnnotation() { + return this.testFrameworkDefinition.orderAnnotation + } + + String getIgnoreAnnotation() { + return this.testFrameworkDefinition.ignoreAnnotation + } + + boolean annotationLevelRules() { + return this.testFrameworkDefinition.annotationLevelRules() + } + + String getRuleAnnotation(String annotationValue) { + return this.testFrameworkDefinition.getRuleAnnotation(annotationValue) + } } 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 e104034cc2..a2c095992d 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 @@ -21,8 +21,16 @@ import java.nio.file.Path import groovy.transform.CompileStatic import groovy.transform.EqualsAndHashCode import groovy.transform.ToString +import org.apache.commons.logging.Log +import org.apache.commons.logging.LogFactory import org.springframework.cloud.contract.spec.Contract +import org.springframework.cloud.contract.spec.internal.DslProperty +import org.springframework.cloud.contract.spec.internal.Headers +import org.springframework.cloud.contract.verifier.util.ContentType +import org.springframework.cloud.contract.verifier.util.ContentUtils +import org.springframework.cloud.contract.verifier.util.NamesUtil +import org.springframework.util.Assert /** * Contains metadata for a particular file with a DSL @@ -32,8 +40,6 @@ import org.springframework.cloud.contract.spec.Contract * @since 1.0.0 */ @CompileStatic -@EqualsAndHashCode -@ToString class ContractMetadata { /** * Path to the file @@ -55,6 +61,10 @@ class ContractMetadata { * The list of contracts for the given file */ final Collection convertedContract = [] + /** + * Converted contracts with meta data information + */ + final Collection convertedContractWithMetadata = [] ContractMetadata(Path path, boolean ignored, int groupSize, Integer order, Contract convertedContract) { this(path, ignored, groupSize, order, [convertedContract]) @@ -66,5 +76,130 @@ class ContractMetadata { this.ignored = ignored this.order = order this.convertedContract.addAll(convertedContract) + this.convertedContractWithMetadata.addAll( + this.convertedContract + .findAll { it != null } + .collect { new SingleContractMetadata(it, this) }) + } +} + +@CompileStatic +@EqualsAndHashCode(excludes = ["contractMetadata"]) +@ToString(excludes = ["contractMetadata"]) +class SingleContractMetadata { + + private static final Log log = LogFactory.getLog(SingleContractMetadata) + + final ContractMetadata contractMetadata + private final File stubsFile + final Contract contract + private final Collection allContracts + final ContentType inputStubContentType + final ContentType evaluatedInputStubContentType + final ContentType outputStubContentType + final ContentType evaluatedOutputStubContentType + final ContentType inputTestContentType + final ContentType evaluatedInputTestContentType + final ContentType outputTestContentType + final ContentType evaluatedOutputTestContentType + private final boolean http + + SingleContractMetadata(Contract currentContract, ContractMetadata contractMetadata) { + this.allContracts = contractMetadata.convertedContract + this.contract = currentContract + Assert.notNull(currentContract, "Contract must not be null") + Headers inputHeaders = inputHeaders(currentContract) + DslProperty inputBody = inputBody(currentContract) + Headers outputHeaders = outputHeaders(currentContract) + DslProperty outputBody = outputBody(currentContract) + this.evaluatedInputTestContentType = ContentUtils.evaluateContentType(inputHeaders, inputBody?.getServerValue()) + this.inputTestContentType = inputBody != null ? this.evaluatedInputTestContentType : ContentType.UNKNOWN + this.evaluatedOutputTestContentType = ContentUtils.evaluateContentType(outputHeaders, outputBody?.getServerValue()) + this.outputTestContentType = outputBody != null ? this.evaluatedOutputTestContentType : ContentType.UNKNOWN + this.evaluatedInputStubContentType = ContentUtils.evaluateContentType(inputHeaders, inputBody?.getClientValue()) + this.inputStubContentType = inputBody != null ? this.evaluatedInputStubContentType : ContentType.UNKNOWN + this.evaluatedOutputStubContentType = ContentUtils.evaluateContentType(outputHeaders, outputBody?.getClientValue()) + this.outputStubContentType = outputBody != null ? this.evaluatedOutputStubContentType : ContentType.UNKNOWN + this.http = currentContract.request != null + this.contractMetadata = contractMetadata + this.stubsFile = contractMetadata.getPath() != null ? contractMetadata.getPath().toFile() : null + } + + boolean isJson() { + return this.inputTestContentType == ContentType.JSON || + this.outputTestContentType == ContentType.JSON || + this.inputStubContentType == ContentType.JSON || + this.outputStubContentType == ContentType.JSON + } + + boolean evaluatesToJson() { + return isJson() || this.evaluatedInputTestContentType == ContentType.JSON || + this.evaluatedOutputTestContentType == ContentType.JSON || + this.evaluatedInputStubContentType == ContentType.JSON || + this.evaluatedOutputStubContentType == ContentType.JSON + } + + boolean isIgnored() { + return this.contract.ignored || this.contractMetadata.ignored + } + + boolean isXml() { + return this.inputTestContentType == ContentType.XML || + this.outputTestContentType == ContentType.XML || + this.inputStubContentType == ContentType.XML || + this.outputStubContentType == ContentType.XML + } + + boolean isHttp() { + return this.http + } + + boolean isMessaging() { + return !isHttp() + } + + private DslProperty inputBody(Contract contract) { + return contract.request?.body ?: contract.input?.messageBody + } + + private Headers inputHeaders(Contract contract) { + return contract.request?.headers ?: contract.input?.messageHeaders + } + + private DslProperty outputBody(Contract contract) { + return contract.response?.body ?: contract.outputMessage?.body + } + + private Headers outputHeaders(Contract contract) { + return contract.response?.headers ?: contract.outputMessage?.headers + } + + String methodName() { + if (contract.name) { + String name = NamesUtil. + camelCase(NamesUtil.convertIllegalPackageChars(contract.name)) + if (log.isDebugEnabled()) { + log.debug("Overriding the default test name with [" + name + "]") + } + return name + } + else if (allContracts.size() > 1) { + int index = allContracts.findIndexOf { it == contract } + String name = "${camelCasedMethodFromFileName(stubsFile)}_${index}" + if (log.isDebugEnabled()) { + log.debug("Scenario found. The method name will be [" + name + "]") + } + return name + } + String name = camelCasedMethodFromFileName(stubsFile) + if (log.isDebugEnabled()) { + log.debug("The method name will be [" + name + "]") + } + return name + } + + private static String camelCasedMethodFromFileName(File stubsFile) { + return NamesUtil.camelCase(NamesUtil.convertIllegalMethodNameChars(NamesUtil. + toLastDot(NamesUtil.afterLast(stubsFile.path, File.separator)))) } } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy index 531ae2c0f5..a592fcc1eb 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentUtils.groovy @@ -16,6 +16,9 @@ package org.springframework.cloud.contract.verifier.util +import java.util.function.Consumer +import java.util.function.Function +import java.util.function.Supplier import java.util.regex.Matcher import java.util.regex.Pattern @@ -121,6 +124,10 @@ class ContentUtils { } } + static Object extractValue(GString bodyAsValue, ContentType contentType, Function valueProvider) { + return extractValue(bodyAsValue, contentType, { valueProvider.apply(it) }) + } + static ContentType getClientContentType(GString bodyAsValue) { try { extractValueForJSON(bodyAsValue, GET_STUB_SIDE) @@ -546,6 +553,18 @@ class ContentUtils { namedContentTypeNameIfPresent(propertyValue, "'") } + static String getGroovyMultipartFileParameterContent(String propertyName, NamedProperty propertyValue, + Function bytesFromFile) { + return "'$propertyName', ${namedPropertyName(propertyValue, "'")}, " + + "${groovyNamedPropertyValue(propertyValue, "'", { FromFileProperty property -> bytesFromFile.apply(property) })}" + + namedContentTypeNameIfPresent(propertyValue, "'") + } + + static String getJavaMultipartFileParameterContent(String propertyName, NamedProperty propertyValue, + Function bytesFromFile) { + return getJavaMultipartFileParameterContent(propertyName, propertyValue, { FromFileProperty property -> bytesFromFile.apply(property) }) + } + static String getJavaMultipartFileParameterContent(String propertyName, NamedProperty propertyValue, Closure bytesFromFile) { return """"${escapeJava(propertyName)}", ${ diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy index 76222e9d62..10022d6f3b 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/JsonToJsonPathsConverter.groovy @@ -92,8 +92,8 @@ class JsonToJsonPathsConverter { } } catch (RuntimeException e) { - if (log.isDebugEnabled()) { - log.debug("Exception occurred while trying to delete path [${matcher.path()}]", e) + if (log.isTraceEnabled()) { + log.trace("Exception occurred while trying to delete path [${matcher.path()}]", e) } } } @@ -106,8 +106,8 @@ class JsonToJsonPathsConverter { return context.read(path) } catch (Exception ex) { - if (log.isDebugEnabled()) { - log.debug("Exception occurred while trying to retrieve element via path [${path}]", ex) + if (log.isTraceEnabled()) { + log.trace("Exception occurred while trying to retrieve element via path [${path}]", ex) } return null } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/MapConverter.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/MapConverter.groovy index 8febf0fc5c..315b35b8ed 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/MapConverter.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/MapConverter.groovy @@ -16,6 +16,8 @@ package org.springframework.cloud.contract.verifier.util +import java.util.function.Function + import groovy.json.JsonSlurper import org.springframework.cloud.contract.spec.internal.DslProperty @@ -40,6 +42,9 @@ class MapConverter { public static final Closure JSON_PARSING_CLOSURE = { String value -> new JsonSlurper().parseText(value) } + public static final Function JSON_PARSING_FUNCTION = { String value -> + new JsonSlurper().parseText(value) + } as Function private final TemplateProcessor templateProcessor @@ -60,6 +65,12 @@ class MapConverter { } } + static Closure fromFunction(Function function) { + return { + function.apply(it) + } + } + /** * Iterates over the structure of the object and executes the closure * on each element of that structure. @@ -161,10 +172,18 @@ class MapConverter { return getClientOrServerSideValues(json, STUB_SIDE, parsingClosure) } + static Object getTestSideValues(json, Function function) { + return getClientOrServerSideValues(json, TEST_SIDE, { function.apply(it) }) + } + static Object getTestSideValues(json, Closure parsingClosure = JSON_PARSING_CLOSURE) { return getClientOrServerSideValues(json, TEST_SIDE, parsingClosure) } + static Object getTestSideValuesForText(json) { + return getClientOrServerSideValues(json, TEST_SIDE, Closure.IDENTITY) + } + static Object getStubSideValuesForNonBody(object) { return getClientOrServerSideValues(object, STUB_SIDE, Closure.IDENTITY) } 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 bd617f5750..306310ebe1 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 @@ -18,7 +18,6 @@ package org.springframework.cloud.contract.verifier import spock.lang.Specification -import org.springframework.cloud.contract.verifier.builder.JavaTestGenerator import org.springframework.cloud.contract.verifier.builder.SingleTestGenerator import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties @@ -26,7 +25,7 @@ import static org.springframework.cloud.contract.verifier.config.TestFramework.S class GeneratorScannerSpec extends Specification { - private JavaTestGenerator classGenerator = Mock(JavaTestGenerator) + private SingleTestGenerator classGenerator = Mock(SingleTestGenerator) def "should find all json files and generate 6 classes for them"() { given: diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilderTests.java b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilderTests.java new file mode 100644 index 0000000000..804ce24131 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/BlockBuilderTests.java @@ -0,0 +1,61 @@ +package org.springframework.cloud.contract.verifier.builder; + +import org.assertj.core.api.BDDAssertions; +import org.junit.Test; + +import static org.junit.Assert.*; + +public class BlockBuilderTests { + + @Test + public void should_add_ending_if_no_special_char_is_at_the_end() { + BlockBuilder blockBuilder = blockBuilder(); + + blockBuilder.append("foo").addEndingIfNotPresent(); + + BDDAssertions.then(blockBuilder.toString()).isEqualTo("foo;"); + + blockBuilder = blockBuilder(); + + blockBuilder.append("foo\n").addEndingIfNotPresent(); + BDDAssertions.then(blockBuilder.toString()).isEqualTo("foo;\n"); + + blockBuilder = blockBuilder(); + + blockBuilder.append( + "DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()))\n") + .addEndingIfNotPresent(); + BDDAssertions.then(blockBuilder.toString()).isEqualTo( + "DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload()));\n"); + } + + @Test + public void should_not_add_ending_if_no_char_is_at_the_end() { + BlockBuilder blockBuilder = blockBuilder(); + + blockBuilder.append("foo;").addEndingIfNotPresent(); + BDDAssertions.then(blockBuilder.toString()).isEqualTo("foo;"); + + blockBuilder = blockBuilder(); + + blockBuilder.append("foo {").addEndingIfNotPresent(); + BDDAssertions.then(blockBuilder.toString()).isEqualTo("foo {"); + + blockBuilder = blockBuilder(); + + blockBuilder.append("foo {\n").addEndingIfNotPresent(); + BDDAssertions.then(blockBuilder.toString()).isEqualTo("foo {\n"); + + blockBuilder = blockBuilder(); + + blockBuilder.append("foo;\n").addEndingIfNotPresent(); + BDDAssertions.then(blockBuilder.toString()).isEqualTo("foo;\n"); + } + + private BlockBuilder blockBuilder() { + BlockBuilder blockBuilder = new BlockBuilder("\t"); + blockBuilder.setupLineEnding(";"); + return blockBuilder; + } + +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilderSpec.groovy index d0b7e64809..36c4eadd5d 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ClassBuilderSpec.groovy @@ -14,7 +14,7 @@ class ClassBuilderSpec extends Specification { given: ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(baseClassForTests: 'a.b.Class') expect: - 'a.b.Class' == ClassBuilder.retrieveBaseClass(props, 'com/example/foo') + 'a.b.Class' == new BaseClassProvider().retrieveBaseClass(props, 'com/example/foo') } def "should return a class from the generated path by taking two last folders when package with base classes is provided"() { @@ -22,7 +22,7 @@ class ClassBuilderSpec extends Specification { ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(packageWithBaseClasses: 'com.example.base') String contractRelativeFolder = ['com', 'example', 'some', 'superpackage'].join(File.separator) expect: - ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SomeSuperpackageBase' + new BaseClassProvider().retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SomeSuperpackageBase' } def "should return a class from the generated path by taking two last folders when package with base classes is provided and contains invalid chars"() { @@ -30,7 +30,7 @@ class ClassBuilderSpec extends Specification { ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(packageWithBaseClasses: 'com.example.base') String contractRelativeFolder = ['com', 'example', 'beer-api-producer-external', 'beer-api-consumer'].join(File.separator) expect: - ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.Beer_api_producer_externalBeer_api_consumerBase' + new BaseClassProvider().retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.Beer_api_producer_externalBeer_api_consumerBase' } def "should return a class from the generated path by taking a single folder when package with base classes is provided and there are not enough package elements"() { @@ -38,7 +38,7 @@ class ClassBuilderSpec extends Specification { ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(packageWithBaseClasses: 'com.example.base') String contractRelativeFolder = 'superpackage' expect: - ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperpackageBase' + new BaseClassProvider().retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperpackageBase' } def "should return a class from mappings regardless of other entries if mapping exists"() { @@ -48,7 +48,7 @@ class ClassBuilderSpec extends Specification { baseClassMappings: ['.*': 'com.example.base.SuperClass']) String contractRelativeFolder = 'superpackage' expect: - ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperClass' + new BaseClassProvider().retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperClass' } @Issue("701") @@ -58,7 +58,7 @@ class ClassBuilderSpec extends Specification { baseClassMappings: ['.*bar.baz.some.*': 'com.example.base.SuperClass']) String contractRelativeFolder = 'foo/bar/baz/some/package'.split("/").join(File.separator) expect: - ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperClass' + new BaseClassProvider().retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperClass' } def "should return the first matching base class when provided mapping doesn't match"() { @@ -69,7 +69,7 @@ class ClassBuilderSpec extends Specification { baseClassMappings: ['patternNotMatchingAnything': 'com.example.base.SuperClass']) String contractRelativeFolder = 'superpackage' expect: - ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperpackageBase' + new BaseClassProvider().retrieveBaseClass(props, contractRelativeFolder) == 'com.example.base.SuperpackageBase' } def "should return a class from the generated path by when external contracts are picked"() { @@ -77,7 +77,7 @@ class ClassBuilderSpec extends Specification { ContractVerifierConfigProperties props = new ContractVerifierConfigProperties(packageWithBaseClasses: "foo.Bar") String contractRelativeFolder = ["org", "springframework", "cloud", "contract", "verifier", "tests", "META_INF", "com.example", "hello_world", "0.1.0_dev.1.uncommitted+d1174dd"].join(File.separator) expect: - ClassBuilder.retrieveBaseClass(props, contractRelativeFolder) == 'foo.Bar.Hello_world0_1_0_dev_1_uncommitted_d1174ddBase' + new BaseClassProvider().retrieveBaseClass(props, contractRelativeFolder) == 'foo.Bar.Hello_world0_1_0_dev_1_uncommitted_d1174ddBase' } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy index 75642ad0df..5348f2751b 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy @@ -19,7 +19,12 @@ package org.springframework.cloud.contract.verifier.builder import spock.lang.Shared import spock.lang.Specification +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.SyntaxChecker /** * Tests used for the documentation @@ -31,6 +36,44 @@ class ContractHttpDocsSpec extends Specification { @Shared ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(assertJsonSize: true) + @Shared + GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod( + new SingleTestGenerator.GeneratedClassData("foo", "bar", new File(".").toPath()), "method") + + @Shared + SingleTestGenerator.GeneratedClassData generatedClassData = + new SingleTestGenerator.GeneratedClassData("foo", "com.example", new File(".").toPath()) + + def setup() { + properties = new ContractVerifierConfigProperties( + assertJsonSize: true + ) + } + + private String singleTestGenerator(Contract contractDsl) { + return new JavaTestGenerator() { + @Override + ClassBodyBuilder classBodyBuilder(BlockBuilder builder, GeneratedClassMetaData metaData, SingleMethodBuilder methodBuilder) { + return super.classBodyBuilder(builder, metaData, methodBuilder).field(new Field() { + @Override + boolean accept() { + return metaData.configProperties.testMode == TestMode.JAXRSCLIENT + } + + @Override + Field call() { + builder.addLine("WebTarget webTarget") + return this + } + }) + } + }.buildClass(properties, [contractMetadata(contractDsl)], "foo", generatedClassData) + } + + private ContractMetadata contractMetadata(Contract contractDsl) { + return new ContractMetadata(new File(".").toPath(), false, 0, null, contractDsl) + } + org.springframework.cloud.contract.spec.Contract httpDsl = // tag::http_dsl[] org.springframework.cloud.contract.spec.Contract.make { @@ -279,6 +322,7 @@ class ContractHttpDocsSpec extends Specification { // tag::optionals[] org.springframework.cloud.contract.spec.Contract.make { priority 1 + name "optionals" request { method 'POST' url '/users/password' @@ -304,36 +348,58 @@ class ContractHttpDocsSpec extends Specification { def 'should convert dsl with optionals to proper Spock test'() { given: - BlockBuilder blockBuilder = new BlockBuilder(" ") - new HttpSpockMethodRequestProcessingBodyBuilder(optionals, properties, new GeneratedClassDataForMethod( - new SingleTestGenerator.GeneratedClassData("foo", "bar", new File(".").toPath()), "method")) - .appendTo(blockBuilder) + properties.testFramework = TestFramework.SPOCK + String test = singleTestGenerator(optionals) expect: String expectedTest = // tag::optionals_test[] - """ - given: - def request = given() - .header("Content-Type", "application/json") - .body('''{"email":"abc@abc.com","callback_url":"https://partners.com"}''') + """\ +package com.example - when: - def response = given().spec(request) - .post("/users/password") +import org.junit.FixMethodOrder +import org.junit.runners.MethodSorters +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import spock.lang.Specification +import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification +import io.restassured.response.ResponseOptions - then: - response.statusCode == 404 - response.header('Content-Type') == 'application/json' - and: - DocumentContext parsedJson = JsonPath.parse(response.body.asString()) - assertThatJson(parsedJson).field("['code']").matches("(123123)?") +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.* +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson +import static io.restassured.module.mockmvc.RestAssuredMockMvc.* + +class FooSpec extends Specification { + +\tdef validate_optionals() throws Exception { +\t\tgiven: +\t\t\tMockMvcRequestSpecification request = given() +\t\t\t\t\t.header("Content-Type", "application/json") +\t\t\t\t\t.body('''{"email":"abc@abc.com","callback_url":"https://partners.com"}''') + +\t\twhen: +\t\t\tResponseOptions response = given().spec(request) +\t\t\t\t\t.post("/users/password") + +\t\tthen: +\t\t\tresponse.statusCode() == 404 +\t\t\tresponse.header("Content-Type") == 'application/json' + +\t\tand: +\t\t\tDocumentContext parsedJson = JsonPath.parse(response.body.asString()) +\t\t\tassertThatJson(parsedJson).field("['code']").matches("(123123)?") +\t} + +} """ // end::optionals_test[] - stripped(blockBuilder.toString()) == stripped(expectedTest) + test.trim() == expectedTest.trim() + and: + SyntaxChecker.tryToCompile("spock", test) } org.springframework.cloud.contract.spec.Contract method = - // tag::method[] + // tag::methodBuilder[] org.springframework.cloud.contract.spec.Contract.make { request { method 'PUT' @@ -355,9 +421,5 @@ class ContractHttpDocsSpec extends Specification { status OK() } } - // end::method[] - - private String stripped(String string) { - return string.stripMargin().stripIndent().replace('\t', '').replace('\n', '').replace(' ', '') - } + // end::methodBuilder[] } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedTestClassTests.java b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedTestClassTests.java new file mode 100644 index 0000000000..e801057c24 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/GeneratedTestClassTests.java @@ -0,0 +1,138 @@ +package org.springframework.cloud.contract.verifier.builder; + +import java.io.File; +import java.io.IOException; +import java.net.URISyntaxException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; + +import org.assertj.core.api.BDDAssertions; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties; +import org.springframework.cloud.contract.verifier.file.ContractMetadata; +import org.springframework.util.FileSystemUtils; + +import static org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter.convertAsCollection; + +public class GeneratedTestClassTests { + + // @formatter:off + String contract = "org.springframework.cloud.contract.spec.Contract.make {\n" + + " name \"foo\"\n" + + " request {\n" + + " method 'PUT'\n" + + " url 'url'\n" + + " headers {\n" + + " header('foo', 'bar')\n" + + " }\n" + + " body (\n" + + " [\"foo1\":\"bar1\"]\n" + + " )\n" + + " }\n" + + " response {\n" + + " status OK()\n" + + " headers {\n" + + " header('foo2', 'bar2')\n" + + " }\n" + + " body (\n" + + " [\"foo3\":\"bar3\"]\n" + + " )\n" + + " }\n" + + "}"; + // @formatter:on + + // @formatter:off + String expectedTest = "package test;\n" ++ "\n" ++ "import BazBar;\n" ++ "import org.junit.FixMethodOrder;\n" ++ "import org.junit.runners.MethodSorters;\n" ++ "import com.jayway.jsonpath.DocumentContext;\n" ++ "import com.jayway.jsonpath.JsonPath;\n" ++ "import org.junit.Test;\n" ++ "import org.junit.Rule;\n" ++ "import org.junit.Ignore;\n" ++ "import org.junit.FixMethodOrder;\n" ++ "import org.junit.runners.MethodSorters;\n" ++ "import io.restassured.module.mockmvc.specification.MockMvcRequestSpecification;\n" ++ "import io.restassured.response.ResponseOptions;\n" ++ "\n" ++ "import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat;\n" ++ "import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*;\n" ++ "import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;\n" ++ "import static io.restassured.module.mockmvc.RestAssuredMockMvc.*;\n" ++ "\n" ++ "@FixMethodOrder(MethodSorters.NAME_ASCENDING)\n" ++ "public class FooBarTest extends BazBar {\n" ++ "\n" ++ "\t@Test\n" ++ "\t@Ignore\n" ++ "\tpublic void validate_foo() throws Exception {\n" ++ "\t\t// given:\n" ++ "\t\t\tMockMvcRequestSpecification request = given()\n" ++ "\t\t\t\t\t.header(\"foo\", \"bar\")\n" ++ "\t\t\t\t\t.body(\"{\\\"foo1\\\":\\\"bar1\\\"}\");\n" ++ "\n" ++ "\t\t// when:\n" ++ "\t\t\tResponseOptions response = given().spec(request)\n" ++ "\t\t\t\t\t.put(\"url\");\n" ++ "\n" ++ "\t\t// then:\n" ++ "\t\t\tassertThat(response.statusCode()).isEqualTo(200);\n" ++ "\t\t\tassertThat(response.header(\"foo2\")).isEqualTo(\"bar2\");\n" ++ "\n" ++ "\t\t// and:\n" ++ "\t\t\tDocumentContext parsedJson = JsonPath.parse(response.getBody().asString());\n" ++ "\t\t\tassertThatJson(parsedJson).field(\"['foo3']\").isEqualTo(\"bar3\");\n" ++ "\t}\n" ++ "\n" ++ "}\n"; + // @formatter:on + + @Rule + public TemporaryFolder tmpFolder = new TemporaryFolder(); + + File file; + + File tmp; + + @Before + public void setup() throws IOException, URISyntaxException { + this.file = this.tmpFolder.newFile(); + Files.write(this.file.toPath(), this.contract.getBytes()); + this.tmp = this.tmpFolder.newFolder(); + File classpath = new File( + GeneratedTestClassTests.class.getResource("/classpath/").toURI()); + FileSystemUtils.copyRecursively(classpath, this.tmp); + } + + @Test + public void should_work_for_junit4_mockmvc_json_non_binary() { + // given + JavaTestGenerator generator = new JavaTestGenerator(); + ContractVerifierConfigProperties configProperties = new ContractVerifierConfigProperties(); + Collection contracts = Collections + .singletonList(new ContractMetadata(this.file.toPath(), true, 1, 2, + convertAsCollection(new File("/"), this.file))); + String includedDirectoryRelativePath = "some/path"; + String convertedClassName = "fooBar"; + String packageName = "test"; + Path classPath = new File("/tmp").toPath(); + configProperties.setBaseClassForTests("BazBar"); + + // when + String builtClass = generator.buildClass(configProperties, contracts, + includedDirectoryRelativePath, new SingleTestGenerator.GeneratedClassData( + convertedClassName, packageName, classPath)); + + // then + BDDAssertions.then(builtClass).isEqualTo(this.expectedTest); + } + +} \ 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 64aebbf871..a36934c29c 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 @@ -26,6 +26,8 @@ import spock.util.environment.RestoreSystemProperties 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.dsl.wiremock.WireMockStubStrategy import org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockStubVerifier import org.springframework.cloud.contract.verifier.file.ContractMetadata @@ -34,11 +36,53 @@ import org.springframework.cloud.contract.verifier.util.SyntaxChecker class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStubVerifier { @Shared - ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(assertJsonSize: true) + ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties( + assertJsonSize: true + ) + + @Shared + SingleTestGenerator.GeneratedClassData generatedClassData = + new SingleTestGenerator.GeneratedClassData("foo", "com.example", new File(".").toPath()) + @Shared GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod( new SingleTestGenerator.GeneratedClassData("foo", "bar", new File(".").toPath()), "method") + def setup() { + properties = new ContractVerifierConfigProperties( + assertJsonSize: true, + testMode: TestMode.JAXRSCLIENT + ) + } + + private String singleTestGenerator(Contract contractDsl) { + return new JavaTestGenerator() { + @Override + ClassBodyBuilder classBodyBuilder(BlockBuilder builder, GeneratedClassMetaData metaData, SingleMethodBuilder methodBuilder) { + return super.classBodyBuilder(builder, metaData, methodBuilder).field(new Field() { + @Override + boolean accept() { + return metaData.configProperties.testMode == TestMode.JAXRSCLIENT + } + + @Override + Field call() { + builder.addLine("WebTarget webTarget") + return this + } + }) + } + }.buildClass(properties, [contractMetadata(contractDsl)], "foo", generatedClassData) + } + + private GeneratedClassMetaData generatedClassMetaData(Contract contractDsl) { + new GeneratedClassMetaData(properties, [contractMetadata(contractDsl)], "foo", generatedClassData) + } + + ContractMetadata contractMetadata(Contract contractDsl) { + return new ContractMetadata(new File(".").toPath(), false, 0, null, contractDsl) + } + @Shared // tag::contract_with_cookies[] Contract contractDslWithCookiesValue = Contract.make { @@ -119,21 +163,24 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub }""" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue("#187") @@ -153,22 +200,25 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub }""" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property3']").isEqualTo(false)""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").isNull()""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("true")""") + test.contains("""assertThatJson(parsedJson).field("['property3']").isEqualTo(false)""") + test.contains("""assertThatJson(parsedJson).field("['property2']").isNull()""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("true")""") and: stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, contractDsl), contractDsl).toWireMockClientStub()) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue("#79") @@ -190,22 +240,25 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, contractDsl), contractDsl).toWireMockClientStub()) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue("#79") @@ -229,23 +282,26 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").hasSize(2)""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").hasSize(2)""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(new WireMockStubStrategy("Test", new ContractMetadata(null, false, 0, null, contractDsl), contractDsl).toWireMockClientStub()) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue("#82") @@ -263,20 +319,23 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains(bodyString) + test.contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyString - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | """entity('{\"items\":[\"HOP\"]}', 'application/json')""" - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'entity("{\\"items\\":[\\"HOP\\"]}", "application/json")' + methodBuilderName | methodBuilder | bodyString + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | """entity("{\\"items\\":[\\"HOP\\"]}", "application/json")""" + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | 'entity("{\\"items\\":[\\"HOP\\"]}", "application/json")' } @Issue("#88") @@ -294,20 +353,23 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains(bodyString) + test.contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyString - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | """entity('property1=VAL1', 'application/octet-stream')""" - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'entity("property1=VAL1", "application/octet-stream")' + methodBuilderName | methodBuilder | bodyString + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | """entity("property1=VAL1", "application/octet-stream")""" + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | 'entity("property1=VAL1", "application/octet-stream")' } def "should generate assertions for array in response body with #methodBuilderName"() { @@ -328,21 +390,24 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub }]""" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("['property1']").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("['property2']").isEqualTo("b")""") + test.contains("""assertThatJson(parsedJson).array().contains("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).array().contains("['property2']").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } def "should generate assertions for array inside response body element with #methodBuilderName"() { @@ -362,21 +427,24 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub }""" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property1']").contains("['property2']").isEqualTo("test1")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property1']").contains("['property3']").isEqualTo("test2")""") + test.contains("""assertThatJson(parsedJson).array("['property1']").contains("['property2']").isEqualTo("test1")""") + test.contains("""assertThatJson(parsedJson).array("['property1']").contains("['property3']").isEqualTo("test2")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } def "should generate assertions for nested objects in response body with #methodBuilderName"() { @@ -396,21 +464,24 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub ''' } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").field("['property3']").isEqualTo("b")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").field("['property3']").isEqualTo("b")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } def "should generate regex assertions for map objects in response body with #methodBodyName"() { @@ -435,21 +506,24 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } def "should generate regex assertions for string objects in response body with #methodBuilderName"() { @@ -467,21 +541,24 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } def "should ignore 'Accept' header and use 'request' method with #methodBuilderName"() { @@ -498,20 +575,23 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains(requestString) + test.contains(requestString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | requestString - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | "request('text/plain')" - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'request("text/plain")' + methodBuilderName | methodBuilder | requestString + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | 'request("text/plain")' + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | 'request("text/plain")' } def "should ignore 'Content-Type' header and use 'entity' method with #methodBuilderName"() { @@ -530,23 +610,26 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: for (String requestString : requestStrings) { - blockBuilder.toString().contains(requestString) + test.contains(requestString) } - !blockBuilder.toString().contains("""Content Type""") + !test.contains("""Content Type""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | requestStrings - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ["""entity('', 'text/plain')""", """header('Timer', '123')"""] - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['entity("\\"\\"", "text/plain")', 'header("Timer", "123")'] + methodBuilderName | methodBuilder | requestStrings + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | ["""entity('', 'text/plain')""", """header('Timer', '123')"""] + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | ['entity("\\"\\"", "text/plain")', 'header("Timer", "123")'] } def "should generate a call with an url path and query parameters with #methodBuilderName"() { @@ -579,30 +662,32 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub """ } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: - test.contains(modifyStringIfRequired.call("queryParam('limit', '10'")) - test.contains(modifyStringIfRequired.call("queryParam('offset', '20'")) - test.contains(modifyStringIfRequired.call("queryParam('filter', 'email'")) - test.contains(modifyStringIfRequired.call("queryParam('sort', 'name'")) - test.contains(modifyStringIfRequired.call("queryParam('search', '55'")) - test.contains(modifyStringIfRequired.call("queryParam('age', '99'")) - test.contains(modifyStringIfRequired.call("queryParam('name', 'Denis.Stepanov'")) - test.contains(modifyStringIfRequired.call("queryParam('email', 'bob@email.com'")) + test.contains(modifyStringIfRequired.call('''queryParam("limit", "10"''')) + test.contains(modifyStringIfRequired.call('''queryParam("offset", "20"''')) + test.contains(modifyStringIfRequired.call('''queryParam("filter", "email"''')) + test.contains(modifyStringIfRequired.call('''queryParam("sort", "name"''')) + test.contains(modifyStringIfRequired.call('''queryParam("search", "55"''')) + test.contains(modifyStringIfRequired.call('''queryParam("age", "99"''')) + test.contains(modifyStringIfRequired.call('''queryParam("name", "Denis.Stepanov"''')) + test.contains(modifyStringIfRequired.call('''queryParam("email", "bob@email.com"''')) test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") test.contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | modifyStringIfRequired - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String paramString -> paramString } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String paramString -> paramString.replace("'", "\"") } + methodBuilderName | methodBuilder | modifyStringIfRequired + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | { String paramString -> paramString } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | { String paramString -> paramString.replace("'", "\"") } } @Issue('#169') @@ -636,30 +721,32 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub """ } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: - test.contains(modifyStringIfRequired.call("queryParam('limit', '10'")) - test.contains(modifyStringIfRequired.call("queryParam('offset', '20'")) - test.contains(modifyStringIfRequired.call("queryParam('filter', 'email'")) - test.contains(modifyStringIfRequired.call("queryParam('sort', 'name'")) - test.contains(modifyStringIfRequired.call("queryParam('search', '55'")) - test.contains(modifyStringIfRequired.call("queryParam('age', '99'")) - test.contains(modifyStringIfRequired.call("queryParam('name', 'Denis.Stepanov'")) - test.contains(modifyStringIfRequired.call("queryParam('email', 'bob@email.com'")) + test.contains(modifyStringIfRequired.call('''queryParam("limit", "10"''')) + test.contains(modifyStringIfRequired.call('''queryParam("offset", "20"''')) + test.contains(modifyStringIfRequired.call('''queryParam("filter", "email"''')) + test.contains(modifyStringIfRequired.call('''queryParam("sort", "name"''')) + test.contains(modifyStringIfRequired.call('''queryParam("search", "55"''')) + test.contains(modifyStringIfRequired.call('''queryParam("age", "99"''')) + test.contains(modifyStringIfRequired.call('''queryParam("name", "Denis.Stepanov"''')) + test.contains(modifyStringIfRequired.call('''queryParam("email", "bob@email.com"''')) test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") test.contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | modifyStringIfRequired - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String paramString -> paramString } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String paramString -> paramString.replace("'", "\"") } + methodBuilderName | methodBuilder | modifyStringIfRequired + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | { String paramString -> paramString } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | { String paramString -> paramString.replace("'", "\"") } } def "should generate test for empty body with #methodBuilderName"() { @@ -675,21 +762,23 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyString - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | "entity('', 'application/octet-stream')" - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'entity("", "application/octet-stream"' + methodBuilderName | methodBuilder | bodyString + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | """entity("", "application/octet-stream")""" + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | """entity("", "application/octet-stream")""" } def "should not parse the response body if there is no response body specified in the contract"() { @@ -703,24 +792,26 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains(bodyParsingString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyParsingString - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | "String responseAsString = response.readEntity(String)" - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | "String responseAsString = response.readEntity(String.class);" + methodBuilderName | methodBuilder | bodyParsingString + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | "String responseAsString = response.readEntity(String)" + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | "String responseAsString = response.readEntity(String.class);" } - def "should generate test for String in response body with #methodBodyName"() { + def "should generate test for String in response body with #methodBuilderName"() { given: Contract contractDsl = Contract.make { request { @@ -732,22 +823,24 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub body "test" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(bodyDefinitionString) test.contains(bodyEvaluationString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | "String responseAsString = response.readEntity(String)" | 'responseBody == "test"' - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'String responseBody = responseAsString;' | 'assertThat(responseBody).isEqualTo("test");' + methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | "String responseAsString = response.readEntity(String)" | 'responseBody == "test"' + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | 'String responseBody = responseAsString;' | 'assertThat(responseBody).isEqualTo("test");' } @Issue('#171') @@ -768,21 +861,23 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub """ } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(methodString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) where: - methodBuilderName | methodBuilder | methodString - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ".method('GET')" - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'method("GET")' + methodBuilderName | methodBuilder | methodString + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | '.build("GET")' + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | 'build("GET")' } def "should generate a call with an url path and query parameters with JUnit - we'll put it into docs"() { @@ -814,43 +909,68 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub """ } } - MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedResponse = // tag::jaxrs[] - ''' - // when: - Response response = webTarget - .path("/users") - .queryParam("limit", "10") - .queryParam("offset", "20") - .queryParam("filter", "email") - .queryParam("sort", "name") - .queryParam("search", "55") - .queryParam("age", "99") - .queryParam("name", "Denis.Stepanov") - .queryParam("email", "bob@email.com") - .request() - .method("GET"); + """\ +package com.example; - String responseAsString = response.readEntity(String.class); +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import org.junit.Test; +import org.junit.Rule; +import javax.ws.rs.client.Entity; +import javax.ws.rs.core.Response; - // then: - assertThat(response.getStatus()).isEqualTo(200); - // and: - DocumentContext parsedJson = JsonPath.parse(responseAsString); - assertThatJson(parsedJson).field("['property1']").isEqualTo("a"); -''' +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; +import static javax.ws.rs.client.Entity.*; + +public class FooTest { +\tWebTarget webTarget; + +\t@Test +\tpublic void validate_() throws Exception { + +\t\t// when: +\t\t\tResponse response = webTarget +\t\t\t\t\t\t\t.path("/users") +\t\t\t\t\t\t\t.queryParam("limit", "10") +\t\t\t\t\t\t\t.queryParam("offset", "20") +\t\t\t\t\t\t\t.queryParam("filter", "email") +\t\t\t\t\t\t\t.queryParam("sort", "name") +\t\t\t\t\t\t\t.queryParam("search", "55") +\t\t\t\t\t\t\t.queryParam("age", "99") +\t\t\t\t\t\t\t.queryParam("name", "Denis.Stepanov") +\t\t\t\t\t\t\t.queryParam("email", "bob@email.com") +\t\t\t\t\t\t\t.request() +\t\t\t\t\t\t\t.build("GET") +\t\t\t\t\t\t\t.invoke(); +\t\t\tString responseAsString = response.readEntity(String.class); + +\t\t// then: +\t\t\tassertThat(response.getStatus()).isEqualTo(200); + +\t\t// and: +\t\t\tDocumentContext parsedJson = JsonPath.parse(responseAsString); +\t\t\tassertThatJson(parsedJson).field("['property1']").isEqualTo("a"); +\t} + +} + +""" // end::jaxrs[] - stripped(test) == stripped(expectedResponse) + test.trim() == expectedResponse.trim() and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompileJava(JaxRsClientJUnitMethodBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileJava("jaxrs", test) } @Issue('#85') @@ -871,11 +991,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub ]) } } - MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason.title"));') } @@ -914,11 +1032,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub ]) } } - MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[0].name")''') test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[1].name")''') @@ -947,11 +1063,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub ]) } } - MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.then(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[0].name")''') test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[1].name")''') @@ -971,15 +1085,13 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub body(value(stub("HELLO FROM STUB"), server(regex(".*")))) } } - MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains("assertThat(responseBody).matches(\".*\");") and: - SyntaxChecker.tryToCompileJava(JaxRsClientJUnitMethodBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileJava("jaxrs", test) } @Issue('#150') @@ -996,15 +1108,13 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub body(value(stub("HELLO FROM STUB"), server(regex(".*")))) } } - MethodBodyBuilder builder = new JaxRsClientSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: - test.contains("responseBody ==~ java.util.regex.Pattern.compile('.*')") + test.contains('responseBody ==~ java.util.regex.Pattern.compile(".*")') and: - SyntaxChecker.tryToCompileGroovy(JaxRsClientJUnitMethodBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileGroovy("jaxrs", test) } @Issue('#150') @@ -1021,11 +1131,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub body(value(stub("HELLO FROM STUB"), server(execute('foo($it)')))) } } - MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains("foo(responseBody);") } @@ -1044,16 +1152,14 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub body(value(stub("HELLO FROM STUB"), server(execute('foo($it)')))) } } - MethodBodyBuilder builder = new JaxRsClientSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains("foo(responseBody)") and: // no static compilation due to bug in Groovy https://issues.apache.org/jira/browse/GROOVY-8055 - SyntaxChecker.tryToCompileGroovy(JaxRsClientJUnitMethodBodyBuilder.simpleName, blockBuilder.toString(), false) + SyntaxChecker.tryToCompileGroovy("jaxrs", test, false) } def "should allow c/p version of consumer producer"() { @@ -1078,21 +1184,24 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue('#149') @@ -1154,11 +1263,9 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).field("[\'aBoolean\']").matches("(true|false)")') test.contains('assertThatJson(parsedJson).field("[\'alpha\']").matches("[\\\\p{L}]*")') @@ -1181,32 +1288,20 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub !test.contains('cursor') !test.contains('REGEXP>>') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) and: String jsonSample = '''\ String json = "{\\"duck\\":\\"8\\",\\"alpha\\":\\"YAJEOWYGMFBEWPMEMAZI\\",\\"number\\":-2095030871,\\"positiveInt\\":42,\\"aDouble\\":42.345,\\"aBoolean\\":true,\\"ip\\":\\"129.168.99.100\\",\\"hostname\\":\\"https://foo389886219.com\\",\\"email\\":\\"foo@bar1367573183.com\\",\\"url\\":\\"https://foo-597104692.com\\",\\"httpsUrl\\":\\"https://baz-486093581.com\\",\\"uuid\\":\\"e436b817-b764-49a2-908e-967f2f99eb9f\\",\\"date\\":\\"2014-04-14\\",\\"dateTime\\":\\"2011-01-11T12:23:34\\",\\"time\\":\\"12:20:30\\",\\"iso8601WithOffset\\":\\"2015-05-15T12:23:34.123Z\\",\\"nonBlankString\\":\\"EPZWVIRHSUAPBJMMQSFO\\",\\"nonEmptyString\\":\\"RVMFDSEQFHRQFVUVQPIA\\",\\"anyOf\\":\\"foo\\"}"; DocumentContext parsedJson = JsonPath.parse(json); ''' - and: - LinkedList lines = [] as LinkedList - test.eachLine { - if (it.contains("assertThatJson")) { - lines << it - } - else { - it - } - } - lines.addFirst(jsonSample) - SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n")) where: - methodBuilderName | methodBuilder | endOfLineRegexSymbol - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - } - - private String stripped(String string) { - return string.stripMargin().stripIndent().replace('\t', '').replace('\n', '').replace(' ', '') + methodBuilderName | methodBuilder | endOfLineRegexSymbol + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | '\\$' + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | '$' } @Issue('#173') @@ -1231,20 +1326,22 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub status(200) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('org.springframework.cloud.contract.spec.internal.OptionalProperty') test.contains('(([0-9]{1,10}))?') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue('#261') @@ -1272,19 +1369,19 @@ DATA body "File name is required" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('entity("\\"\\n') test.contains('''entity("\\n--Boundary_1_1831312172_1491482784697\\nContent-Disposition: form-data; name=\\"file\\"\\n\\nDATA\\n--Boundary_1_1831312172_1491482784697--\\n", "multipart/form-data;boundary=Boundary_1_1831312172_1491482784697"))''') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue('#261') @@ -1305,106 +1402,94 @@ DATA body "File name is required" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('entity("\\"\\n') - test.contains('''.method("POST", entity("{\\"foo\\":\\"bar\\"}", "application/json"))''') + test.contains('''.build("POST", entity("{\\"foo\\":\\"bar\\"}", "application/json"))''') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } def "should generate test for cookies with string value in JAX-RS JUnit test"() { given: - MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDslWithCookiesValue, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithCookiesValue) then: test.contains('''.cookie("cookie-key", "cookie-value")''') test.contains('''assertThat(response.getCookies().get("cookie-key")).isNotNull();''') test.contains('''assertThat(response.getCookies().get("cookie-key").getValue()).isEqualTo("new-cookie-value");''') and: - SyntaxChecker.tryToCompile("JaxRsClientJUnitMethodBodyBuilder", blockBuilder.toString()) + SyntaxChecker.tryToCompile("jaxrs", test) } def "should generate test for cookies with pattern in JAX-RS JUnit test"() { given: - MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDslWithCookiesPattern, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithCookiesPattern) then: !test.contains('''.cookie("cookie-key", "[A-Za-z]+")''') test.contains('''.cookie("cookie-key", "''') test.contains('''assertThat(response.getCookies().get("cookie-key")).isNotNull();''') test.contains('''assertThat(response.getCookies().get("cookie-key").getValue()).matches("[A-Za-z]+");''') and: - SyntaxChecker.tryToCompile("JaxRsClientJUnitMethodBodyBuilder", blockBuilder.toString()) + SyntaxChecker.tryToCompile("jaxrs", test) } def "should not generate cookie assertions with absent value in JAX-RS JUnit test"() { given: - MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDslWithAbsentCookies, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithAbsentCookies) then: !test.contains("cookie") and: - SyntaxChecker.tryToCompile("JaxRsClientJunitMethodBodyBuilder", blockBuilder.toString()) + SyntaxChecker.tryToCompile("jaxrs", test) } def "should generate test for cookies with string value in JAX-RS Spock test"() { given: - MethodBodyBuilder builder = new JaxRsClientSpockMethodRequestProcessingBodyBuilder(contractDslWithCookiesValue, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithCookiesValue) then: test.contains('''.cookie('cookie-key', 'cookie-value')''') - test.contains('''response.getCookies().get('cookie-key') != null''') - test.contains("response.getCookies().get('cookie-key').getValue() == 'new-cookie-value'") + test.contains('''response.getCookies().get("cookie-key") != null''') + test.contains('response.getCookies().get("cookie-key").getValue() == "new-cookie-value"') and: - SyntaxChecker.tryToCompile("JaxRsClientSpockMethodRequestProcessingBodyBuilder", blockBuilder.toString()) + SyntaxChecker.tryToCompile("jaxrs-spock", test) } def "should generate test for cookies with pattern in JAX-RS Spock test"() { given: - MethodBodyBuilder builder = new JaxRsClientSpockMethodRequestProcessingBodyBuilder(contractDslWithCookiesPattern, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithCookiesPattern) then: !test.contains('''.cookie('cookie-key', '[A-Za-z]+')''') test.contains('''.cookie('cookie-key', ''') - test.contains('''response.getCookies().get('cookie-key') != null''') - test.contains('''response.getCookies().get('cookie-key').getValue() ==~ java.util.regex.Pattern.compile('[A-Za-z]+')''') + test.contains('''response.getCookies().get("cookie-key") != null''') + test.contains('''response.getCookies().get("cookie-key").getValue() ==~ java.util.regex.Pattern.compile("[A-Za-z]+")''') and: - SyntaxChecker.tryToCompile("JaxRsClientSpockMethodRequestProcessingBodyBuilder", blockBuilder.toString()) + SyntaxChecker.tryToCompile("jaxrs-spock", test) } def "should not generate cookie assertions with absent value in JAX-RS Spock test"() { given: - MethodBodyBuilder builder = new JaxRsClientSpockMethodRequestProcessingBodyBuilder(contractDslWithAbsentCookies, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithAbsentCookies) then: !test.contains("cookie") and: - SyntaxChecker.tryToCompile("JaxRsClientSpockMethodRequestProcessingBodyBuilder", blockBuilder.toString()) + SyntaxChecker.tryToCompile("jaxrs-spock", test) } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy index 029306bce9..b0c76a4b24 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy @@ -22,6 +22,9 @@ import spock.lang.Specification 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.SyntaxChecker /** @@ -31,16 +34,51 @@ import org.springframework.cloud.contract.verifier.util.SyntaxChecker class MessagingMethodBodyBuilderSpec extends Specification { @Shared - ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties(assertJsonSize: true, generatedTestSourcesDir: new File("."), - generatedTestResourcesDir: new File(".")) + ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties( + assertJsonSize: true + ) + @Shared - GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod( - new SingleTestGenerator.GeneratedClassData("foo", "bar", new File("target/test.java").toPath()), "method") + SingleTestGenerator.GeneratedClassData generatedClassData = + new SingleTestGenerator.GeneratedClassData("foo", "com.example", new File(MessagingMethodBodyBuilderSpec.getResource(".").toURI()).toPath()) + + def setup() { + properties = new ContractVerifierConfigProperties( + assertJsonSize: true, + generatedTestSourcesDir: new File(MessagingMethodBodyBuilderSpec.getResource(".").toURI()), + generatedTestResourcesDir: new File(MessagingMethodBodyBuilderSpec.getResource(".").toURI()) + ) + } + + private String singleTestGenerator(Contract contractDsl) { + return new JavaTestGenerator() { + @Override + ClassBodyBuilder classBodyBuilder(BlockBuilder builder, GeneratedClassMetaData metaData, SingleMethodBuilder methodBuilder) { + return super.classBodyBuilder(builder, metaData, methodBuilder).field(new Field() { + @Override + boolean accept() { + return metaData.configProperties.testMode == TestMode.JAXRSCLIENT + } + + @Override + Field call() { + builder.addLine("WebTarget webTarget") + return this + } + }) + } + }.buildClass(properties, [contractMetadata(contractDsl)], "foo", generatedClassData) + } + + private ContractMetadata contractMetadata(Contract contractDsl) { + return new ContractMetadata(new File(".").toPath(), false, 0, null, contractDsl) + } def "should work for triggered based messaging with Spock"() { given: // tag::trigger_method_dsl[] def contractDsl = Contract.make { + name "foo" label 'some_label' input { triggeredBy('bookReturnedTriggered()') @@ -55,35 +93,65 @@ class MessagingMethodBodyBuilderSpec extends Specification { } } // end::trigger_method_dsl[] - MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMessage = // tag::trigger_method_test[] - ''' - when: - bookReturnedTriggered() + '''\ +package com.example - then: - ContractVerifierMessage response = contractVerifierMessaging.receive('activemq:output') - assert response != null - response.getHeader('BOOK-NAME')?.toString() == 'foo' - response.getHeader('contentType')?.toString() == 'application/json' - and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload)) - assertThatJson(parsedJson).field("bookName").isEqualTo("foo") +import org.junit.FixMethodOrder +import org.junit.runners.MethodSorters +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import spock.lang.Specification +import javax.inject.Inject +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.* +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes + +class FooSpec extends Specification { +\t@Inject ContractVerifierMessaging contractVerifierMessaging +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper + +\tdef validate_foo() throws Exception { +\t\twhen: +\t\t\tbookReturnedTriggered() + +\t\tthen: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("activemq:output") +\t\t\tresponse != null + +\t\tand: +\t\t\tresponse.getHeader("BOOK-NAME") != null +\t\t\tresponse.getHeader("BOOK-NAME").toString() == 'foo' +\t\t\tresponse.getHeader("contentType") != null +\t\t\tresponse.getHeader("contentType").toString() == 'application/json' + +\t\tand: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())) +\t\t\tassertThatJson(parsedJson).field("['bookName']").isEqualTo("foo") +\t} + +} ''' // end::trigger_method_test[] - stripped(test) == stripped(expectedMessage) + test.trim() == expectedMessage.trim() } def "should work for triggered based messaging with JUnit"() { given: def contractDsl = Contract.make { + name "foo" label 'some_label' input { triggeredBy('bookReturnedTriggered()') @@ -97,37 +165,69 @@ class MessagingMethodBodyBuilderSpec extends Specification { } } } - MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMessage = // tag::trigger_method_junit_test[] - ''' - // when: - bookReturnedTriggered(); + '''\ +package com.example; + +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import org.junit.Test; +import org.junit.Rule; +import javax.inject.Inject; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging; + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes; + +public class FooTest { +\t@Inject ContractVerifierMessaging contractVerifierMessaging; +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper; + +\t@Test +\tpublic void validate_foo() throws Exception { +\t\t// when: +\t\t\tbookReturnedTriggered(); + +\t\t// then: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("activemq:output"); +\t\t\tassertThat(response).isNotNull(); + +\t\t// and: +\t\t\tassertThat(response.getHeader("BOOK-NAME")).isNotNull(); +\t\t\tassertThat(response.getHeader("BOOK-NAME").toString()).isEqualTo("foo"); +\t\t\tassertThat(response.getHeader("contentType")).isNotNull(); +\t\t\tassertThat(response.getHeader("contentType").toString()).isEqualTo("application/json"); + +\t\t// and: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); +\t\t\tassertThatJson(parsedJson).field("['bookName']").isEqualTo("foo"); +\t} + +} - // then: - ContractVerifierMessage response = contractVerifierMessaging.receive("activemq:output"); - assertThat(response).isNotNull(); - assertThat(response.getHeader("BOOK-NAME")).isNotNull(); - assertThat(response.getHeader("BOOK-NAME").toString()).isEqualTo("foo"); - assertThat(response.getHeader("contentType")).isNotNull(); - assertThat(response.getHeader("contentType").toString()).isEqualTo("application/json"); - // and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); - assertThatJson(parsedJson).field("bookName").isEqualTo("foo"); ''' // end::trigger_method_junit_test[] - stripped(test) == stripped(expectedMessage) + test.trim() == expectedMessage.trim() } def "should generate tests triggered by a message for Spock"() { given: // tag::trigger_message_dsl[] def contractDsl = Contract.make { + name "foo" label 'some_label' input { messageFrom('jms:input') @@ -149,39 +249,70 @@ class MessagingMethodBodyBuilderSpec extends Specification { } } // end::trigger_message_dsl[] - MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMessage = // tag::trigger_message_spock[] """\ -given: - ContractVerifierMessage inputMessage = contractVerifierMessaging.create( - '''{"bookName":"foo"}''', - ['sample': 'header'] - ) +package com.example -when: - contractVerifierMessaging.send(inputMessage, 'jms:input') +import org.junit.FixMethodOrder +import org.junit.runners.MethodSorters +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import spock.lang.Specification +import javax.inject.Inject +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.* +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes + +class FooSpec extends Specification { +\t@Inject ContractVerifierMessaging contractVerifierMessaging +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper + +\tdef validate_foo() throws Exception { +\t\tgiven: +\t\t\tContractVerifierMessage inputMessage = contractVerifierMessaging.create( +\t\t\t\t\t'''{"bookName":"foo"}''' +\t\t\t\t\t\t, headers() +\t\t\t\t\t\t\t.header("sample", "header") +\t\t\t) + +\t\twhen: +\t\t\tcontractVerifierMessaging.send(inputMessage, "jms:input") + +\t\tthen: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("jms:output") +\t\t\tresponse != null + +\t\tand: +\t\t\tresponse.getHeader("BOOK-NAME") != null +\t\t\tresponse.getHeader("BOOK-NAME").toString() == 'foo' + +\t\tand: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())) +\t\t\tassertThatJson(parsedJson).field("['bookName']").isEqualTo("foo") +\t} + +} -then: - ContractVerifierMessage response = contractVerifierMessaging.receive('jms:output') - assert response !- null - response.getHeader('BOOK-NAME')?.toString() == 'foo' -and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload)) - assertThatJson(parsedJson).field("bookName").isEqualTo("foo") """ // end::trigger_message_spock[] - stripped(test) == stripped(expectedMessage) + test.trim() == expectedMessage.trim() } def "should generate tests triggered by a message for JUnit"() { given: def contractDsl = Contract.make { + name "foo" label 'some_label' input { messageFrom('jms:input') @@ -202,41 +333,74 @@ and: } } } - MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMessage = // tag::trigger_message_junit[] - ''' -// given: - ContractVerifierMessage inputMessage = contractVerifierMessaging.create( - "{\\"bookName\\":\\"foo\\"}" -, headers() - .header("sample", "header")); + '''\ +package com.example; -// when: - contractVerifierMessaging.send(inputMessage, "jms:input"); +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import org.junit.Test; +import org.junit.Rule; +import javax.inject.Inject; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging; + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes; + +public class FooTest { +\t@Inject ContractVerifierMessaging contractVerifierMessaging; +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper; + +\t@Test +\tpublic void validate_foo() throws Exception { +\t\t// given: +\t\t\tContractVerifierMessage inputMessage = contractVerifierMessaging.create( +\t\t\t\t\t"{\\"bookName\\":\\"foo\\"}" +\t\t\t\t\t\t, headers() +\t\t\t\t\t\t\t.header("sample", "header") +\t\t\t); + +\t\t// when: +\t\t\tcontractVerifierMessaging.send(inputMessage, "jms:input"); + +\t\t// then: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("jms:output"); +\t\t\tassertThat(response).isNotNull(); + +\t\t// and: +\t\t\tassertThat(response.getHeader("BOOK-NAME")).isNotNull(); +\t\t\tassertThat(response.getHeader("BOOK-NAME").toString()).isEqualTo("foo"); + +\t\t// and: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); +\t\t\tassertThatJson(parsedJson).field("['bookName']").isEqualTo("foo"); +\t} + +} -// then: - ContractVerifierMessage response = contractVerifierMessaging.receive("jms:output"); - assertThat(response).isNotNull(); - assertThat(response.getHeader("BOOK-NAME")).isNotNull(); - assertThat(response.getHeader("BOOK-NAME").toString()).isEqualTo("foo"); -// and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); - assertThatJson(parsedJson).field("bookName").isEqualTo("foo"); ''' // end::trigger_message_junit[] - stripped(test) == stripped(expectedMessage) + test.trim() == expectedMessage.trim() } def "should generate tests without destination, triggered by a message"() { given: // tag::trigger_no_output_dsl[] def contractDsl = Contract.make { + name "foo" label 'some_label' input { messageFrom('jms:delete') @@ -250,35 +414,61 @@ and: } } // end::trigger_no_output_dsl[] - MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMsg = // tag::trigger_no_output_spock[] - ''' -given: - ContractVerifierMessage inputMessage = contractVerifierMessaging.create( - \'\'\'{"bookName":"foo"}\'\'\', - ['sample': 'header'] - ) + """\ +package com.example -when: - contractVerifierMessaging.send(inputMessage, 'jms:delete') +import org.junit.FixMethodOrder +import org.junit.runners.MethodSorters +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import spock.lang.Specification +import javax.inject.Inject +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging -then: - noExceptionThrown() - bookWasDeleted() -''' +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.* +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes + +class FooSpec extends Specification { +\t@Inject ContractVerifierMessaging contractVerifierMessaging +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper + +\tdef validate_foo() throws Exception { +\t\tgiven: +\t\t\tContractVerifierMessage inputMessage = contractVerifierMessaging.create( +\t\t\t\t\t'''{"bookName":"foo"}''' +\t\t\t\t\t\t, headers() +\t\t\t\t\t\t\t.header("sample", "header") +\t\t\t) + +\t\twhen: +\t\t\tcontractVerifierMessaging.send(inputMessage, "jms:delete") +\t\t\tbookWasDeleted() + +\t\tthen: +\t\t\tnoExceptionThrown() +\t} + +} +""" // end::trigger_no_output_spock[] - stripped(test) == stripped(expectedMsg) + test.trim() == expectedMsg.trim() } def "should generate tests without destination, triggered by a message for JUnit"() { given: def contractDsl = Contract.make { + name "foo" label 'some_label' input { messageFrom('jms:delete') @@ -291,34 +481,63 @@ then: assertThat('bookWasDeleted()') } } - MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMsg = // tag::trigger_no_output_junit[] - ''' -// given: - ContractVerifierMessage inputMessage = contractVerifierMessaging.create( - "{\\"bookName\\":\\"foo\\"}" -, headers() - .header("sample", "header")); + """\ +package com.example; -// when: - contractVerifierMessaging.send(inputMessage, "jms:delete"); +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import org.junit.Test; +import org.junit.Rule; +import javax.inject.Inject; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging; -// then: - bookWasDeleted(); -''' +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes; + +public class FooTest { +\t@Inject ContractVerifierMessaging contractVerifierMessaging; +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper; + +\t@Test +\tpublic void validate_foo() throws Exception { +\t\t// given: +\t\t\tContractVerifierMessage inputMessage = contractVerifierMessaging.create( +\t\t\t\t\t"{\\"bookName\\":\\"foo\\"}" +\t\t\t\t\t\t, headers() +\t\t\t\t\t\t\t.header("sample", "header") +\t\t\t); + +\t\t// when: +\t\t\tcontractVerifierMessaging.send(inputMessage, "jms:delete"); +\t\t\tbookWasDeleted(); + +\t} + +} + +""" // end::trigger_no_output_junit[] - stripped(test) == stripped(expectedMsg) + test.trim() == expectedMsg.trim() } def "should generate tests without headers for JUnit"() { given: def contractDsl = Contract.make { + name "foo" label 'some_label' input { messageFrom('jms:input') @@ -336,38 +555,65 @@ then: ]) } } - MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMsg = - ''' - // given: - ContractVerifierMessage inputMessage = contractVerifierMessaging.create( - "{\\"bookName\\":\\"foo\\"}" - , headers() - .header("sample", "header")); + """\ +package com.example; - // when: - contractVerifierMessaging.send(inputMessage, "jms:input"); +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import org.junit.Test; +import org.junit.Rule; +import javax.inject.Inject; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging; - // then: - ContractVerifierMessage response = contractVerifierMessaging.receive("jms:output"); - assertThat(response).isNotNull(); - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); - assertThatJson(parsedJson).field("bookName").isEqualTo("foo"); -''' - stripped(test) == stripped(expectedMsg) - and: 'indents are maintained' - test.contains(" ContractVerifierMessage response") - test.contains(" DocumentContext parsedJson") +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes; + +public class FooTest { +\t@Inject ContractVerifierMessaging contractVerifierMessaging; +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper; + +\t@Test +\tpublic void validate_foo() throws Exception { +\t\t// given: +\t\t\tContractVerifierMessage inputMessage = contractVerifierMessaging.create( +\t\t\t\t\t"{\\"bookName\\":\\"foo\\"}" +\t\t\t\t\t\t, headers() +\t\t\t\t\t\t\t.header("sample", "header") +\t\t\t); + +\t\t// when: +\t\t\tcontractVerifierMessaging.send(inputMessage, "jms:input"); + +\t\t// then: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("jms:output"); +\t\t\tassertThat(response).isNotNull(); + +\t\t// and: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); +\t\t\tassertThatJson(parsedJson).field("['bookName']").isEqualTo("foo"); +\t} + +} +""" + test.trim() == expectedMsg.trim() } def "should generate tests without headers for Spock"() { given: def contractDsl = Contract.make { + name "foo" label 'some_label' input { messageFrom('jms:input') @@ -385,30 +631,58 @@ then: ]) } } - MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMsg = - """ - given: - ContractVerifierMessage inputMessage = contractVerifierMessaging.create('''{"bookName":"foo"}''' - ,[ - 'sample': 'header' - ]) + """\ +package com.example - when: - contractVerifierMessaging.send(inputMessage, 'jms:input') +import org.junit.FixMethodOrder +import org.junit.runners.MethodSorters +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import spock.lang.Specification +import javax.inject.Inject +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.* +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes + +class FooSpec extends Specification { +\t@Inject ContractVerifierMessaging contractVerifierMessaging +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper + +\tdef validate_foo() throws Exception { +\t\tgiven: +\t\t\tContractVerifierMessage inputMessage = contractVerifierMessaging.create( +\t\t\t\t\t'''{"bookName":"foo"}''' +\t\t\t\t\t\t, headers() +\t\t\t\t\t\t\t.header("sample", "header") +\t\t\t) + +\t\twhen: +\t\t\tcontractVerifierMessaging.send(inputMessage, "jms:input") + +\t\tthen: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("jms:output") +\t\t\tresponse != null + +\t\tand: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())) +\t\t\tassertThatJson(parsedJson).field("['bookName']").isEqualTo("foo") +\t} + +} - then: - ContractVerifierMessage response = contractVerifierMessaging.receive('jms:output') - assert response != null - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload)) - assertThatJson(parsedJson).field("bookName").isEqualTo("foo") """ - stripped(test) == stripped(expectedMsg) + test.trim() == expectedMsg.trim() } private String stripped(String text) { @@ -420,6 +694,7 @@ then: def contractDsl = // tag::consumer_producer[] Contract.make { + name "foo" label 'some_label' input { messageFrom value(consumer('jms:output'), producer('jms:input')) @@ -438,30 +713,60 @@ then: } } // end::consumer_producer[] - MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMsg = ''' - // given: - ContractVerifierMessage inputMessage = contractVerifierMessaging.create( - "{\\"bookName\\":\\"foo\\"}" - , headers() - .header("sample", "header")); +package com.example; - // when: - contractVerifierMessaging.send(inputMessage, "jms:input"); +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import org.junit.Test; +import org.junit.Rule; +import javax.inject.Inject; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging; - // then: - ContractVerifierMessage response = contractVerifierMessaging.receive("jms:output"); - assertThat(response).isNotNull(); - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); - assertThatJson(parsedJson).field("bookName").isEqualTo("foo"); +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes; + +public class FooTest { +\t@Inject ContractVerifierMessaging contractVerifierMessaging; +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper; + +\t@Test +\tpublic void validate_foo() throws Exception { +\t\t// given: +\t\t\tContractVerifierMessage inputMessage = contractVerifierMessaging.create( +\t\t\t\t\t"{\\"bookName\\":\\"foo\\"}" +\t\t\t\t\t\t, headers() +\t\t\t\t\t\t\t.header("sample", "header") +\t\t\t); + +\t\t// when: +\t\t\tcontractVerifierMessaging.send(inputMessage, "jms:input"); + +\t\t// then: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("jms:output"); +\t\t\tassertThat(response).isNotNull(); + +\t\t// and: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); +\t\t\tassertThatJson(parsedJson).field("['bookName']").isEqualTo("foo"); +\t} + +} ''' - stripped(test) == stripped(expectedMsg) + test.trim() == expectedMsg.trim() } @Issue("336") @@ -469,6 +774,7 @@ then: given: def contractDsl = org.springframework.cloud.contract.spec.Contract.make { + name "foo" label 'trigger_event' input { @@ -485,27 +791,58 @@ then: ]) } } - MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMsg = - ''' - // when: - requestIsCalled(); + """\ +package com.example; - // then: - ContractVerifierMessage response = contractVerifierMessaging.receive("topic.rateablequote"); - assertThat(response).isNotNull(); - assertThat(response.getHeader("processId")).isNotNull(); - assertThat(response.getHeader("processId").toString()).matches("[0-9]+"); - // and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); - assertThatJson(parsedJson).field("['eventId']").matches("[0-9]+"); -''' - stripped(test) == stripped(expectedMsg) +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import org.junit.Test; +import org.junit.Rule; +import javax.inject.Inject; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging; + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes; + +public class FooTest { +\t@Inject ContractVerifierMessaging contractVerifierMessaging; +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper; + +\t@Test +\tpublic void validate_foo() throws Exception { +\t\t// when: +\t\t\trequestIsCalled(); + +\t\t// then: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("topic.rateablequote"); +\t\t\tassertThat(response).isNotNull(); + +\t\t// and: +\t\t\tassertThat(response.getHeader("processId")).isNotNull(); +\t\t\tassertThat(response.getHeader("processId").toString()).matches("[0-9]+"); + +\t\t// and: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); +\t\t\tassertThatJson(parsedJson).field("['eventId']").matches("[0-9]+"); +\t} + +} + +""" + test.trim() == expectedMsg.trim() } @Issue("567") @@ -513,6 +850,7 @@ then: given: def contractDsl = org.springframework.cloud.contract.spec.Contract.make { + name "foo" label 'trigger_event' input { @@ -529,11 +867,10 @@ then: ]) } } - MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThat(response.getHeader("processId").toString()).matches("\\\\d+");') } @@ -544,6 +881,7 @@ then: given: //tag::regex_creating_props[] Contract contractDsl = Contract.make { + name "foo" label 'trigger_event' input { triggeredBy('toString()') @@ -574,11 +912,9 @@ then: } } //end::regex_creating_props[] - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).field("[\'aBoolean\']").matches("(true|false)")') test.contains('assertThatJson(parsedJson).field("[\'alpha\']").matches("[\\\\p{L}]*")') @@ -602,34 +938,11 @@ then: !test.contains('cursor') !test.contains('REGEXP>>') and: - String jsonSample = '''\ - String json = "{\\"shouldFail\\":123,\\"duck\\":\\"8\\",\\"alpha\\":\\"YAJEOWYGMFBEWPMEMAZI\\",\\"number\\":-2095030871,\\"anInteger\\":1780305902,\\"positiveInt\\":345,\\"aDouble\\":42.345,\\"aBoolean\\":true,\\"ip\\":\\"129.168.99.100\\",\\"hostname\\":\\"https://foo389886219.com\\",\\"email\\":\\"foo@bar1367573183.com\\",\\"url\\":\\"https://foo-597104692.com\\",\\"httpsUrl\\":\\"https://baz-486093581.com\\",\\"uuid\\":\\"e436b817-b764-49a2-908e-967f2f99eb9f\\",\\"date\\":\\"2014-04-14\\",\\"dateTime\\":\\"2011-01-11T12:23:34\\",\\"time\\":\\"12:20:30\\",\\"iso8601WithOffset\\":\\"2015-05-15T12:23:34.123Z\\",\\"nonBlankString\\":\\"EPZWVIRHSUAPBJMMQSFO\\",\\"nonEmptyString\\":\\"RVMFDSEQFHRQFVUVQPIA\\",\\"anyOf\\":\\"foo\\"}"; - DocumentContext parsedJson = JsonPath.parse(json); - ''' - and: - LinkedList lines = [] as LinkedList - test.eachLine { - if (it.contains("assertThatJson")) { - lines << it - } - else { - it - } - } - lines.addFirst(jsonSample) - lines.addLast('''assertThatJson(parsedJson).field("['shouldFail']").matches("(\\\\d\\\\d\\\\d\\\\d)-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])");''') - String assertionsOnly = lines.join("\n") - and: - SyntaxChecker.tryToCompile(methodBuilderName, assertionsOnly) - when: - SyntaxChecker.tryToRun(methodBuilderName, assertionsOnly) - then: - Exception error = thrown(Exception) - (error.message ? error.message : error.cause.message).contains('''doesn't match the JSON path [$[?(@.['shouldFail'] =~ ''') + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | endOfLineRegExSymbol - "SpockMessagingMethodBodyBuilder" | { Contract dsl -> new SpockMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - "JUnitMessagingMethodBodyBuilder" | { Contract dsl -> new JUnitMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' + methodBuilderName | methodBuilder | endOfLineRegExSymbol + "spock" | { properties.testFramework = TestFramework.SPOCK } | '\\$' + "junit" | { properties.testFramework = TestFramework.JUNIT } | '$' } @Issue("587") @@ -637,6 +950,7 @@ then: given: def contractDsl = org.springframework.cloud.contract.spec.Contract.make { + name "foo" label 'trigger_event' input { @@ -653,11 +967,10 @@ then: ]) } } - MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('ContractVerifierMessage response = contractVerifierMessaging.receive("topic.rateablequote")') test.contains('assertThat(response).isNotNull()') @@ -672,6 +985,7 @@ then: given: def contractDsl = org.springframework.cloud.contract.spec.Contract.make { + name "foo" label 'trigger_event' input { @@ -688,26 +1002,54 @@ then: ]) } } - MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMsg = - ''' - when: - requestIsCalled() + """\ +package com.example - then: - ContractVerifierMessage response = contractVerifierMessaging.receive('topic.rateablequote') - assert response != null - response.getHeader('processId')?.toString() ==~ java.util.regex.Pattern.compile('[0-9]+') - and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload)) - assertThatJson(parsedJson).field("['eventId']").matches("[0-9]+") -''' - stripped(test) == stripped(expectedMsg) +import org.junit.FixMethodOrder +import org.junit.runners.MethodSorters +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import spock.lang.Specification +import javax.inject.Inject +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.* +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes + +class FooSpec extends Specification { +\t@Inject ContractVerifierMessaging contractVerifierMessaging +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper + +\tdef validate_foo() throws Exception { +\t\twhen: +\t\t\trequestIsCalled() + +\t\tthen: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("topic.rateablequote") +\t\t\tresponse != null + +\t\tand: +\t\t\tresponse.getHeader("processId") != null +\t\t\tresponse.getHeader("processId").toString() ==~ java.util.regex.Pattern.compile('[0-9]+') + +\t\tand: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())) +\t\t\tassertThatJson(parsedJson).field("['eventId']").matches("[0-9]+") +\t} + +} +""" + test.trim() == expectedMsg.trim() } @Issue("587") @@ -715,6 +1057,7 @@ then: given: def contractDsl = org.springframework.cloud.contract.spec.Contract.make { + name "foo" label 'trigger_event' input { @@ -731,26 +1074,54 @@ then: ]) } } - MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMsg = - ''' - when: - requestIsCalled() + """\ +package com.example - then: - ContractVerifierMessage response = contractVerifierMessaging.receive('topic.rateablequote') - assert response != null - response.getHeader('processId')?.toString() ==~ java.util.regex.Pattern.compile('[\\S\\s]+') - and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload)) - assertThatJson(parsedJson).field("['eventId']").matches("[\\S\\s]+") -''' - stripped(test) == stripped(expectedMsg) +import org.junit.FixMethodOrder +import org.junit.runners.MethodSorters +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import spock.lang.Specification +import javax.inject.Inject +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.* +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes + +class FooSpec extends Specification { +\t@Inject ContractVerifierMessaging contractVerifierMessaging +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper + +\tdef validate_foo() throws Exception { +\t\twhen: +\t\t\trequestIsCalled() + +\t\tthen: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("topic.rateablequote") +\t\t\tresponse != null + +\t\tand: +\t\t\tresponse.getHeader("processId") != null +\t\t\tresponse.getHeader("processId").toString() ==~ java.util.regex.Pattern.compile('[\\\\S\\\\s]+') + +\t\tand: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())) +\t\t\tassertThatJson(parsedJson).field("['eventId']").matches("[\\\\S\\\\s]+") +\t} + +} +""" + test.trim() == expectedMsg.trim() } @Issue("440") @@ -758,6 +1129,7 @@ then: given: def contractDsl = org.springframework.cloud.contract.spec.Contract.make { + name "foo" label 'trigger_event' input { @@ -774,26 +1146,54 @@ then: ]) } } - MethodBodyBuilder builder = new SpockMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMsg = - ''' - when: - requestIsCalled() + """\ +package com.example - then: - ContractVerifierMessage response = contractVerifierMessaging.receive(toString()) - assert response != null - response.getHeader('processId')?.toString() ==~ java.util.regex.Pattern.compile('[0-9]+') - and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload)) - assertThatJson(parsedJson).field("['eventId']").matches("[0-9]+") -''' - stripped(test) == stripped(expectedMsg) +import org.junit.FixMethodOrder +import org.junit.runners.MethodSorters +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import spock.lang.Specification +import javax.inject.Inject +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.* +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes + +class FooSpec extends Specification { +\t@Inject ContractVerifierMessaging contractVerifierMessaging +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper + +\tdef validate_foo() throws Exception { +\t\twhen: +\t\t\trequestIsCalled() + +\t\tthen: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive(toString()) +\t\t\tresponse != null + +\t\tand: +\t\t\tresponse.getHeader("processId") != null +\t\t\tresponse.getHeader("processId").toString() ==~ java.util.regex.Pattern.compile('[0-9]+') + +\t\tand: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())) +\t\t\tassertThatJson(parsedJson).field("['eventId']").matches("[0-9]+") +\t} + +} +""" + test.trim() == expectedMsg.trim() } @Issue("440") @@ -801,6 +1201,7 @@ then: given: def contractDsl = org.springframework.cloud.contract.spec.Contract.make { + name "foo" label 'trigger_event' input { @@ -817,37 +1218,68 @@ then: ]) } } - MethodBodyBuilder builder = new JUnitMessagingMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: String expectedMsg = - ''' - // when: - requestIsCalled(); + """\ +package com.example; - // then: - ContractVerifierMessage response = contractVerifierMessaging.receive(toString()); - assertThat(response).isNotNull(); - assertThat(response.getHeader("processId")).isNotNull(); - assertThat(response.getHeader("processId").toString()).matches("[0-9]+"); - // and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); - assertThatJson(parsedJson).field("['eventId']").matches("[0-9]+"); -''' - stripped(test) == stripped(expectedMsg) +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import org.junit.Test; +import org.junit.Rule; +import javax.inject.Inject; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging; + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes; + +public class FooTest { +\t@Inject ContractVerifierMessaging contractVerifierMessaging; +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper; + +\t@Test +\tpublic void validate_foo() throws Exception { +\t\t// when: +\t\t\trequestIsCalled(); + +\t\t// then: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive(toString()); +\t\t\tassertThat(response).isNotNull(); + +\t\t// and: +\t\t\tassertThat(response.getHeader("processId")).isNotNull(); +\t\t\tassertThat(response.getHeader("processId").toString()).matches("[0-9]+"); + +\t\t// and: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); +\t\t\tassertThatJson(parsedJson).field("['eventId']").matches("[0-9]+"); +\t} + +} +""" + test.trim() == expectedMsg.trim() } @Issue('#620') def "should generate tests with message headers containing regular expression which compile for [#methodBuilderName]"() { given: Contract contractDsl = Contract.make { + name "foo" label 'shouldPublishMessage' // input to the contract input { - // the contract will be triggered by a method + // the contract will be triggered by a methodBuilder triggeredBy('foo()') } // output message of the contract @@ -863,46 +1295,108 @@ then: } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('cursor') !test.contains('REGEXP>>') - test == expectedTest + test.trim() == expectedTest.trim() where: - methodBuilderName | methodBuilder | expectedTest - "SpockMessagingMethodBodyBuilder" | { Contract dsl -> new SpockMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ''' when: - foo() + methodBuilderName | methodBuilder | expectedTest + "spock" | { properties.testFramework = TestFramework.SPOCK } | """\ +package com.example - then: - ContractVerifierMessage response = contractVerifierMessaging.receive('messageExchange') - assert response != null - response.getHeader('Authorization')?.toString() ==~ java.util.regex.Pattern.compile('Bearer [A-Za-z0-9-._~+/]+=*') - and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload)) - assertThatJson(parsedJson).field("['field']").isEqualTo("value") -''' - "JUnitMessagingMethodBodyBuilder" | { Contract dsl -> new JUnitMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ''' // when: - foo(); +import org.junit.FixMethodOrder +import org.junit.runners.MethodSorters +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import spock.lang.Specification +import javax.inject.Inject +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging - // then: - ContractVerifierMessage response = contractVerifierMessaging.receive("messageExchange"); - assertThat(response).isNotNull(); - assertThat(response.getHeader("Authorization")).isNotNull(); - assertThat(response.getHeader("Authorization").toString()).matches("Bearer [A-Za-z0-9\\\\-\\\\._~\\\\+\\\\/]+=*"); - // and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); - assertThatJson(parsedJson).field("['field']").isEqualTo("value"); -''' +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.* +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes + +class FooSpec extends Specification { +\t@Inject ContractVerifierMessaging contractVerifierMessaging +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper + +\tdef validate_foo() throws Exception { +\t\twhen: +\t\t\tfoo() + +\t\tthen: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("messageExchange") +\t\t\tresponse != null + +\t\tand: +\t\t\tresponse.getHeader("Authorization") != null +\t\t\tresponse.getHeader("Authorization").toString() ==~ java.util.regex.Pattern.compile('Bearer [A-Za-z0-9\\\\-\\\\._~\\\\+\\\\/]+=*') + +\t\tand: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())) +\t\t\tassertThatJson(parsedJson).field("['field']").isEqualTo("value") +\t} + +} +""" + "junit" | { properties.testFramework = TestFramework.JUNIT } | """\ +package com.example; + +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import org.junit.Test; +import org.junit.Rule; +import javax.inject.Inject; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging; + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes; + +public class FooTest { +\t@Inject ContractVerifierMessaging contractVerifierMessaging; +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper; + +\t@Test +\tpublic void validate_foo() throws Exception { +\t\t// when: +\t\t\tfoo(); + +\t\t// then: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("messageExchange"); +\t\t\tassertThat(response).isNotNull(); + +\t\t// and: +\t\t\tassertThat(response.getHeader("Authorization")).isNotNull(); +\t\t\tassertThat(response.getHeader("Authorization").toString()).matches("Bearer [A-Za-z0-9\\\\-\\\\._~\\\\+\\\\/]+=*"); + +\t\t// and: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); +\t\t\tassertThatJson(parsedJson).field("['field']").isEqualTo("value"); +\t} + +} +""" } @Issue('#664') def "should generate tests for messages having binary payloads [#methodBuilderName]"() { given: Contract contractDsl = Contract.make { + name "foo" label 'shouldPublishMessage' input { messageFrom("foo") @@ -919,59 +1413,110 @@ then: } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('cursor') !test.contains('REGEXP>>') - test == expectedTest + test.trim() == expectedTest.trim() where: - methodBuilderName | methodBuilder | expectedTest - "SpockMessagingMethodBodyBuilder" | { Contract dsl -> new SpockMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ''' given: - ContractVerifierMessage inputMessage = contractVerifierMessaging.create( - fileToBytes(this, "method_request_request.pdf") + methodBuilderName | methodBuilder | expectedTest + "spock" | { properties.testFramework = TestFramework.SPOCK } | """\ +package com.example - ,[ - "contentType": "application/octet-stream" - ]) +import spock.lang.Specification +import javax.inject.Inject +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging - when: - contractVerifierMessaging.send(inputMessage, 'foo') +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.* +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes - then: - ContractVerifierMessage response = contractVerifierMessaging.receive('messageExchange') - assert response != null - response.getHeader('contentType')?.toString() == 'application/octet-stream\' - and: - response.payloadAsByteArray == fileToBytes(this, "method_response_response.pdf") -''' - "JUnitMessagingMethodBodyBuilder" | { Contract dsl -> new JUnitMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ''' // given: - ContractVerifierMessage inputMessage = contractVerifierMessaging.create( -\t\t\t\tfileToBytes(this, "method_request_request.pdf") -\t\t\t\t, headers() -\t\t\t\t\t\t.header("contentType", "application/octet-stream") +class FooSpec extends Specification { +\t@Inject ContractVerifierMessaging contractVerifierMessaging +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper + +\tdef validate_foo() throws Exception { +\t\tgiven: +\t\t\tContractVerifierMessage inputMessage = contractVerifierMessaging.create( +\t\t\t\t\tfileToBytes(this, "foo_request_request.pdf") +\t\t\t\t\t\t, headers() +\t\t\t\t\t\t\t.header("contentType", "application/octet-stream") +\t\t\t) + +\t\twhen: +\t\t\tcontractVerifierMessaging.send(inputMessage, "foo") + +\t\tthen: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("messageExchange") +\t\t\tresponse != null + +\t\tand: +\t\t\tresponse.getHeader("contentType") != null +\t\t\tresponse.getHeader("contentType").toString() == 'application/octet-stream' + +\t\tand: +\t\t\tresponse.getPayloadAsByteArray() == fileToBytes(this, "foo_response_response.pdf") +\t} + +} +""" + "junit" | { properties.testFramework = TestFramework.JUNIT } | """\ +package com.example; + +import org.junit.Test; +import org.junit.Rule; +import javax.inject.Inject; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging; + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes; + +public class FooTest { +\t@Inject ContractVerifierMessaging contractVerifierMessaging; +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper; + +\t@Test +\tpublic void validate_foo() throws Exception { +\t\t// given: +\t\t\tContractVerifierMessage inputMessage = contractVerifierMessaging.create( +\t\t\t\t\tfileToBytes(this, "foo_request_request.pdf") +\t\t\t\t\t\t, headers() +\t\t\t\t\t\t\t.header("contentType", "application/octet-stream") \t\t\t); - // when: - contractVerifierMessaging.send(inputMessage, "foo"); +\t\t// when: +\t\t\tcontractVerifierMessaging.send(inputMessage, "foo"); - // then: - ContractVerifierMessage response = contractVerifierMessaging.receive("messageExchange"); - assertThat(response).isNotNull(); - assertThat(response.getHeader("contentType")).isNotNull(); - assertThat(response.getHeader("contentType").toString()).isEqualTo("application/octet-stream"); - // and: - assertThat(response.getPayloadAsByteArray()).isEqualTo(fileToBytes(this, "method_response_response.pdf")); -''' +\t\t// then: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("messageExchange"); +\t\t\tassertThat(response).isNotNull(); + +\t\t// and: +\t\t\tassertThat(response.getHeader("contentType")).isNotNull(); +\t\t\tassertThat(response.getHeader("contentType").toString()).isEqualTo("application/octet-stream"); + +\t\t// and: +\t\t\tassertThat(response.getPayloadAsByteArray()).isEqualTo(fileToBytes(this, "foo_response_response.pdf")); +\t} + +} +""" } @Issue('#650') def "should generate output for message [#methodBuilderName]"() { given: Contract contractDsl = org.springframework.cloud.contract.spec.Contract.make { + name "foo" description 'issue #650' label 'trigger' input { @@ -999,62 +1544,127 @@ then: ]) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('cursor') !test.contains('REGEXP>>') - test == expectedTest + test.trim() == expectedTest.trim() where: - methodBuilderName | methodBuilder | expectedTest - "SpockMessagingMethodBodyBuilder" | { Contract dsl -> new SpockMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ''' when: - createNewPerson() + methodBuilderName | methodBuilder | expectedTest + "spock" | { properties.testFramework = TestFramework.SPOCK } | """\ +package com.example - then: - ContractVerifierMessage response = contractVerifierMessaging.receive('personEventsTopic') - assert response != null - response.getHeader('contentType')?.toString() == 'application/json' - response.getHeader('type')?.toString() == 'person' - response.getHeader('eventType')?.toString() == 'PersonChangedEvent' - response.getHeader('customerId')?.toString() ==~ java.util.regex.Pattern.compile('[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}') - and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.payload)) - assertThatJson(parsedJson).field("['lastName']").matches("[\\\\S\\\\s]+") - assertThatJson(parsedJson).field("['userId']").matches("([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})?") - assertThatJson(parsedJson).field("['middleName']").matches("([\\\\S\\\\s]+)?") - assertThatJson(parsedJson).field("['version']").matches("-?(\\\\d*\\\\.\\\\d+|\\\\d+)") - assertThatJson(parsedJson).field("['uid']").matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}") - assertThatJson(parsedJson).field("['type']").isEqualTo("CREATED") - assertThatJson(parsedJson).field("['personId']").matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}") - assertThatJson(parsedJson).field("['firstName']").matches("[\\\\S\\\\s]+") -''' - "JUnitMessagingMethodBodyBuilder" | { Contract dsl -> new JUnitMessagingMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ''' // when: - createNewPerson(); +import org.junit.FixMethodOrder +import org.junit.runners.MethodSorters +import com.jayway.jsonpath.DocumentContext +import com.jayway.jsonpath.JsonPath +import spock.lang.Specification +import javax.inject.Inject +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging - // then: - ContractVerifierMessage response = contractVerifierMessaging.receive("personEventsTopic"); - assertThat(response).isNotNull(); - assertThat(response.getHeader("contentType")).isNotNull(); - assertThat(response.getHeader("contentType").toString()).isEqualTo("application/json"); - assertThat(response.getHeader("type")).isNotNull(); - assertThat(response.getHeader("type").toString()).isEqualTo("person"); - assertThat(response.getHeader("eventType")).isNotNull(); - assertThat(response.getHeader("eventType").toString()).isEqualTo("PersonChangedEvent"); - assertThat(response.getHeader("customerId")).isNotNull(); - assertThat(response.getHeader("customerId").toString()).matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"); - // and: - DocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); - assertThatJson(parsedJson).field("['lastName']").matches("[\\\\S\\\\s]+"); - assertThatJson(parsedJson).field("['userId']").matches("([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})?"); - assertThatJson(parsedJson).field("['middleName']").matches("([\\\\S\\\\s]+)?"); - assertThatJson(parsedJson).field("['version']").matches("-?(\\\\d*\\\\.\\\\d+|\\\\d+)"); - assertThatJson(parsedJson).field("['uid']").matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"); - assertThatJson(parsedJson).field("['type']").isEqualTo("CREATED"); - assertThatJson(parsedJson).field("['personId']").matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"); - assertThatJson(parsedJson).field("['firstName']").matches("[\\\\S\\\\s]+"); -''' +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.* +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes + +class FooSpec extends Specification { +\t@Inject ContractVerifierMessaging contractVerifierMessaging +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper + +\tdef validate_foo() throws Exception { +\t\twhen: +\t\t\tcreateNewPerson() + +\t\tthen: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("personEventsTopic") +\t\t\tresponse != null + +\t\tand: +\t\t\tresponse.getHeader("contentType") != null +\t\t\tresponse.getHeader("contentType").toString() == 'application/json' +\t\t\tresponse.getHeader("type") != null +\t\t\tresponse.getHeader("type").toString() == 'person' +\t\t\tresponse.getHeader("eventType") != null +\t\t\tresponse.getHeader("eventType").toString() == 'PersonChangedEvent' +\t\t\tresponse.getHeader("customerId") != null +\t\t\tresponse.getHeader("customerId").toString() ==~ java.util.regex.Pattern.compile('[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}') + +\t\tand: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())) +\t\t\tassertThatJson(parsedJson).field("['lastName']").matches("[\\\\S\\\\s]+") +\t\t\tassertThatJson(parsedJson).field("['userId']").matches("([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})?") +\t\t\tassertThatJson(parsedJson).field("['middleName']").matches("([\\\\S\\\\s]+)?") +\t\t\tassertThatJson(parsedJson).field("['version']").matches("-?(\\\\d*\\\\.\\\\d+|\\\\d+)") +\t\t\tassertThatJson(parsedJson).field("['uid']").matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}") +\t\t\tassertThatJson(parsedJson).field("['type']").isEqualTo("CREATED") +\t\t\tassertThatJson(parsedJson).field("['personId']").matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}") +\t\t\tassertThatJson(parsedJson).field("['firstName']").matches("[\\\\S\\\\s]+") +\t} + +} +""" + "junit" | { properties.testFramework = TestFramework.JUNIT } | """\ +package com.example; + +import org.junit.FixMethodOrder; +import org.junit.runners.MethodSorters; +import com.jayway.jsonpath.DocumentContext; +import com.jayway.jsonpath.JsonPath; +import org.junit.Test; +import org.junit.Rule; +import javax.inject.Inject; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessage; +import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierMessaging; + +import static org.springframework.cloud.contract.verifier.assertion.SpringCloudContractAssertions.assertThat; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.*; +import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson; +import static org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers; +import static org.springframework.cloud.contract.verifier.util.ContractVerifierUtil.fileToBytes; + +public class FooTest { +\t@Inject ContractVerifierMessaging contractVerifierMessaging; +\t@Inject ContractVerifierObjectMapper contractVerifierObjectMapper; + +\t@Test +\tpublic void validate_foo() throws Exception { +\t\t// when: +\t\t\tcreateNewPerson(); + +\t\t// then: +\t\t\tContractVerifierMessage response = contractVerifierMessaging.receive("personEventsTopic"); +\t\t\tassertThat(response).isNotNull(); + +\t\t// and: +\t\t\tassertThat(response.getHeader("contentType")).isNotNull(); +\t\t\tassertThat(response.getHeader("contentType").toString()).isEqualTo("application/json"); +\t\t\tassertThat(response.getHeader("type")).isNotNull(); +\t\t\tassertThat(response.getHeader("type").toString()).isEqualTo("person"); +\t\t\tassertThat(response.getHeader("eventType")).isNotNull(); +\t\t\tassertThat(response.getHeader("eventType").toString()).isEqualTo("PersonChangedEvent"); +\t\t\tassertThat(response.getHeader("customerId")).isNotNull(); +\t\t\tassertThat(response.getHeader("customerId").toString()).matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"); + +\t\t// and: +\t\t\tDocumentContext parsedJson = JsonPath.parse(contractVerifierObjectMapper.writeValueAsString(response.getPayload())); +\t\t\tassertThatJson(parsedJson).field("['lastName']").matches("[\\\\S\\\\s]+"); +\t\t\tassertThatJson(parsedJson).field("['userId']").matches("([a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12})?"); +\t\t\tassertThatJson(parsedJson).field("['middleName']").matches("([\\\\S\\\\s]+)?"); +\t\t\tassertThatJson(parsedJson).field("['version']").matches("-?(\\\\d*\\\\.\\\\d+|\\\\d+)"); +\t\t\tassertThatJson(parsedJson).field("['uid']").matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"); +\t\t\tassertThatJson(parsedJson).field("['type']").isEqualTo("CREATED"); +\t\t\tassertThatJson(parsedJson).field("['personId']").matches("[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}"); +\t\t\tassertThatJson(parsedJson).field("['firstName']").matches("[\\\\S\\\\s]+"); +\t} + +} + +""" } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy index 726b0ac834..4a5f042cbc 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBodyBuilderSpec.groovy @@ -17,7 +17,6 @@ package org.springframework.cloud.contract.verifier.builder -import java.lang.reflect.InvocationTargetException import org.junit.Rule import spock.lang.Issue @@ -27,8 +26,11 @@ import spock.lang.Specification import org.springframework.boot.test.rule.OutputCapture 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.converter.YamlContractConverter import org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockStubVerifier +import org.springframework.cloud.contract.verifier.file.ContractMetadata import org.springframework.cloud.contract.verifier.util.ContractVerifierDslConverter import org.springframework.cloud.contract.verifier.util.SyntaxChecker @@ -37,19 +39,48 @@ class MethodBodyBuilderSpec extends Specification implements WireMockStubVerifie @Rule OutputCapture capture = new OutputCapture() - @Shared - GeneratedClassDataForMethod classDataForMethod = new GeneratedClassDataForMethod( - new SingleTestGenerator.GeneratedClassData("ClassName", "com.example", - new File("target/test.java").toPath()), - "some_method" - ) - @Shared ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties( assertJsonSize: true, generatedTestSourcesDir: new File("."), generatedTestResourcesDir: new File(".") ) + @Shared + SingleTestGenerator.GeneratedClassData generatedClassData = + new SingleTestGenerator.GeneratedClassData("foo", "com.example", new File(MethodBodyBuilderSpec.getResource(".").toURI()).toPath()) + + def setup() { + properties = new ContractVerifierConfigProperties( + assertJsonSize: true, + generatedTestSourcesDir: new File(MethodBodyBuilderSpec.getResource(".").toURI()), + generatedTestResourcesDir: new File(MethodBodyBuilderSpec.getResource(".").toURI()) + ) + } + + private String singleTestGenerator(Contract contractDsl) { + return new JavaTestGenerator() { + @Override + ClassBodyBuilder classBodyBuilder(BlockBuilder builder, GeneratedClassMetaData metaData, SingleMethodBuilder methodBuilder) { + return super.classBodyBuilder(builder, metaData, methodBuilder).field(new Field() { + @Override + boolean accept() { + return metaData.configProperties.testMode == TestMode.JAXRSCLIENT + } + + @Override + Field call() { + builder.addLine("WebTarget webTarget") + return this + } + }) + } + }.buildClass(properties, [contractMetadata(contractDsl)], "foo", generatedClassData) + } + + private ContractMetadata contractMetadata(Contract contractDsl) { + return new ContractMetadata(new File(".").toPath(), false, 0, null, contractDsl) + } + @Issue('#251') def 'should work with execute and arrays [#methodBuilderName]'() { given: @@ -97,41 +128,32 @@ class MethodBodyBuilderSpec extends Specification implements WireMockStubVerifie } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('$.myArray.[0].anotherArrayNeededForBug.[0].optionalNotEmpty') !test.contains('cursor') !test.contains('REGEXP>>') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) - and: - String jsonSample = '''\ -String json = "{\\"myArray\\":[{\\"notABugGeneratedHere\\":\\"foo\\",\\"anotherArrayNeededForBug\\":[{\\"optionalNotEmpty\\":\\"12\\"}],\\"yetAnotherArrayNeededForBug\\":[{\\"optionalNotEmpty\\":\\"22\\"}]},{\\"anotherArrayNeededForBug2\\":[{\\"optionalNotEmpty\\":\\"122\\"}]}]}"; -DocumentContext parsedJson = JsonPath.parse(json); -''' - and: - LinkedList lines = [] as LinkedList - test.eachLine { - if (it.contains("assertThatJson") || it.contains("assertThat((String")) { - lines << it - } - else { - it - } - } - lines.addFirst(jsonSample) - SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n")) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#588') @@ -149,23 +171,31 @@ DocumentContext parsedJson = JsonPath.parse(json); ]) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('d+') !test.contains('REGEXP>>') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#521') @@ -188,22 +218,29 @@ DocumentContext parsedJson = JsonPath.parse(json); ]) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + methodBuilder() + String test = singleTestGenerator(contractDsl) assert !test.contains('REGEXP>>') - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) } where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#269') @@ -225,41 +262,32 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''$.foo.['my.dotted.response']''') !test.contains('cursor') !test.contains('REGEXP>>') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) - and: - String jsonSample = '''\ -String json = "{\\"foo\\":{\\"my.dotted.response\\":\\"foo\\"}}"; -DocumentContext parsedJson = JsonPath.parse(json); -''' - and: - LinkedList lines = [] as LinkedList - test.eachLine { - if (it.contains('"foo".equals')) { - lines << it - } - else { - it - } - } - lines.addFirst(jsonSample) - SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n")) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#289') @@ -283,46 +311,28 @@ DocumentContext parsedJson = JsonPath.parse(json); ]) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) - and: - String jsonSample = '''\ -String json = "{}"; -DocumentContext parsedJson = JsonPath.parse(json); -''' - and: - LinkedList lines = [] as LinkedList - test.eachLine { - if (it.contains('assertThatJson')) { - lines << it - } - else { - it - } - } - lines.addFirst(jsonSample) - try { - SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n")) - } - catch (IllegalStateException e) { - assert e.message.contains("Parsed JSON [{}] doesn't match the JSON path") - } - catch (InvocationTargetException e1) { - assert e1.cause.message. - contains("Parsed JSON [{}] doesn't match the JSON path") - } + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#313') @@ -342,21 +352,29 @@ DocumentContext parsedJson = JsonPath.parse(json); } } //end::body_execute[] - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) !test.contains("executionCommand") where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#318') @@ -384,36 +402,44 @@ DocumentContext parsedJson = JsonPath.parse(json); } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: SyntaxChecker.tryToCompile(methodBuilderName, test) asserter(test) where: - methodBuilderName | methodBuilder | asserter - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody -> - testBody.contains("response.header('Content-Length') == 4") && testBody. - contains("response.header('Content-Type') ==~ java.util.regex.Pattern.compile('application/pdf.*')") + methodBuilderName | methodBuilder | asserter + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | { String testBody -> + testBody.contains('response.header("Content-Length") == 4') && testBody. + contains('''response.header("Content-Type") ==~ java.util.regex.Pattern.compile('application/pdf.*')''') } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody -> + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | { String testBody -> testBody. contains('assertThat(response.header("Content-Length")).isEqualTo(4);') && testBody. contains('assertThat(response.header("Content-Type")).matches("application/pdf.*");') } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody -> + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | { String testBody -> testBody. - contains("response.getHeaderString('Content-Length') == 4") && testBody. - contains(" response.getHeaderString('Content-Type') ==~ java.util.regex.Pattern.compile('application/pdf.*')") + contains("""response.getHeaderString("Content-Length") == 4""") && testBody. + contains("""response.getHeaderString("Content-Type") ==~ java.util.regex.Pattern.compile("application/pdf.*")""") } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody -> + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | { String testBody -> testBody. contains('assertThat(response.getHeaderString("Content-Length")).isEqualTo(4);') && testBody. contains('assertThat(response.getHeaderString("Content-Type")).matches("application/pdf.*");') } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testBody -> + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | { String testBody -> testBody. contains('assertThat(response.header("Content-Length")).isEqualTo(4);') && testBody. contains('assertThat(response.header("Content-Type")).matches("application/pdf.*");') @@ -435,28 +461,36 @@ DocumentContext parsedJson = JsonPath.parse(json); ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString(). + test. contains("""assertThatJson(parsedJson).field("['createdAt']").isEqualTo(1502766000000L)""") - blockBuilder.toString(). + test. contains("""assertThatJson(parsedJson).field("['updatedAt']").isEqualTo(1499476115000L)""") and: SyntaxChecker. - tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder. - toString()) + tryToCompileWithoutCompileStatic(methodBuilderName, test) and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#424') @@ -474,25 +508,33 @@ DocumentContext parsedJson = JsonPath.parse(json); status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - !blockBuilder.toString().contains('myheader') + !test.contains('myheader') and: SyntaxChecker. - tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder. - toString()) + tryToCompileWithoutCompileStatic(methodBuilderName, test) and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#458') @@ -509,31 +551,39 @@ DocumentContext parsedJson = JsonPath.parse(json); body fromRequest().body('$.name') } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) responseAsserter(test) and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder | responseAsserter - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> - string.contains('responseBody == "My name"') + methodBuilderName | methodBuilder | responseAsserter + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | { String string -> + string.contains("responseBody == '''My name'''") } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | { String string -> string.contains('assertThat(responseBody).isEqualTo("My name");') } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | { String string -> string.contains('responseBody == "My name"') } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | { String string -> string.contains('assertThat(responseBody).isEqualTo("My name");') } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | { String string -> string.contains('assertThat(responseBody).isEqualTo("My name");') } } @@ -560,24 +610,32 @@ DocumentContext parsedJson = JsonPath.parse(json); ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) test.contains('''assertThatJson(parsedJson).field("['foo']").isEqualTo("bar")''') test.contains('''assertThatJson(parsedJson).field("['number']").isEqualTo(1)''') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#702') @@ -617,24 +675,32 @@ DocumentContext parsedJson = JsonPath.parse(json); ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) test.contains('''assertThatJson(parsedJson).field("['updatedTs']").isEqualTo(1531916906000L)''') !test.contains('''"updatedTs":"1531916906000"''') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#465') @@ -663,22 +729,30 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } def 'should use fixed delay milliseconds in the generated test [#methodBuilderName]'() { @@ -695,20 +769,23 @@ DocumentContext parsedJson = JsonPath.parse(json); body(a: 'foo') } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains(""".timeout(10000)""") + test.contains(""".timeout(10000)""") and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } } @Issue('#493') @@ -727,23 +804,31 @@ DocumentContext parsedJson = JsonPath.parse(json); status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains('a=abc&b=123') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#578') @@ -783,23 +868,31 @@ DocumentContext parsedJson = JsonPath.parse(json); ]) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) test.contains('username=user&password=password&grant_type=password') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#493') @@ -835,23 +928,31 @@ DocumentContext parsedJson = JsonPath.parse(json); ]) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains('&') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } def 'should work with files that have new lines [#methodBuilderName]'() { @@ -873,26 +974,33 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) test.contains('''assertThatJson(parsedJson).field("['status']").isEqualTo("RESPONSE")''') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } - @Issue('#509') def 'classToCheck() should return class of object'() { given: @@ -905,27 +1013,24 @@ DocumentContext parsedJson = JsonPath.parse(json); status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) + ClassVerifier verifier = new TestClassVerifier() when: Map map = new LinkedHashMap<>() Integer number = Integer.valueOf(42) List list = new ArrayList<>() Set set = new HashSet<>() then: - builder.classToCheck(map) == Map.class + verifier.classToCheck(map) == Map.class and: - builder.classToCheck(number) == Integer.class + verifier.classToCheck(number) == Integer.class and: - builder.classToCheck(list) == List.class + verifier.classToCheck(list) == List.class and: - builder.classToCheck(set) == Set.class - where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + verifier.classToCheck(set) == Set.class + } + + class TestClassVerifier implements ClassVerifier { + } def 'should assert null values without matchers [#methodBuilderName]'() { @@ -942,26 +1047,34 @@ DocumentContext parsedJson = JsonPath.parse(json); ]) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString(). + test. contains("""assertThatJson(parsedJson).field("['nullValue']").isNull()""") and: SyntaxChecker. - tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder. - toString()) + tryToCompileWithoutCompileStatic(methodBuilderName, test) and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } def 'should not escape a regex pattern when matching raw body value [#methodBuilderName]'() { @@ -979,63 +1092,79 @@ DocumentContext parsedJson = JsonPath.parse(json); body(value(stub("1"), test(regex(pattern)))) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() test.contains(escapedPattern) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue("#664") def 'should work with binary payload for [#methodBuilderName]'() { given: File root = new File("src/test/resources/body_builder/") - Contract contract = ContractVerifierDslConverter.convertAsCollection(root, + Contract contractDsl = ContractVerifierDslConverter.convertAsCollection(root, new File(root, "worksWithPdf.groovy")).first() - MethodBodyBuilder builder = methodBuilder(contract) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() requestMatcher(test) responseMatcher(test) SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | requestMatcher | responseMatcher - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> - string.contains('.body(fileToBytes(this, "some_method_request_request.pdf"))') - } | { String string -> - string.contains('response.body.asByteArray() == fileToBytes(this, "some_method_response_response.pdf")') + methodBuilderName | methodBuilder | requestMatcher | responseMatcher + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | { String string -> + string.contains('.body(fileToBytes(this, "worksWithPdf_request_request.pdf"))') + } | { String string -> + string.contains('response.body.asByteArray() == fileToBytes(this, "worksWithPdf_response_response.pdf")') } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> - string.contains('.body(fileToBytes(this, "some_method_request_request.pdf"));') - } | { String string -> - string.contains('assertThat(response.getBody().asByteArray()).isEqualTo(fileToBytes(this, "some_method_response_response.pdf"));') + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | { String string -> + string.contains('.body(fileToBytes(this, "worksWithPdf_request_request.pdf"));') + } | { String string -> + string.contains('assertThat(response.getBody().asByteArray()).isEqualTo(fileToBytes(this, "worksWithPdf_response_response.pdf"));') } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> - string.contains('entity(fileToBytes(this, "some_method_request_request.pdf")') - } | { String string -> - string.contains('response.readEntity(byte[]) == fileToBytes(this, "some_method_response_response.pdf")') + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | { String string -> + string.contains('entity(fileToBytes(this, "worksWithPdf_request_request.pdf")') + } | { String string -> + string.contains('response.readEntity(byte[]) == fileToBytes(this, "worksWithPdf_response_response.pdf")') } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> - string.contains('entity(fileToBytes(this, "some_method_request_request.pdf")') - } | { String string -> - string.contains('assertThat(response.readEntity(byte[].class)).isEqualTo(fileToBytes(this, "some_method_response_response.pdf"));') + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | { String string -> + string.contains('entity(fileToBytes(this, "worksWithPdf_request_request.pdf")') + } | { String string -> + string.contains('assertThat(response.readEntity(byte[].class)).isEqualTo(fileToBytes(this, "worksWithPdf_response_response.pdf"));') } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String string -> - string.contains('.body(fileToBytes(this, "some_method_request_request.pdf"));') - } | { String string -> - string.contains('assertThat(response.getBody().asByteArray()).isEqualTo(fileToBytes(this, "some_method_response_response.pdf"));') + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | { String string -> + string.contains('.body(fileToBytes(this, "worksWithPdf_request_request.pdf"));') + } | { String string -> + string.contains('assertThat(response.getBody().asByteArray()).isEqualTo(fileToBytes(this, "worksWithPdf_response_response.pdf"));') } } @@ -1091,23 +1220,31 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains('''assertThatJson(parsedJson).array("['toyDetails']").field("['dimensions']").isEmpty()''') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue("#852") @@ -1132,22 +1269,28 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains('''.isEqualTo("\\\\"escaped\\\\"")''') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - "MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue("#844") @@ -1183,22 +1326,28 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains('''assertThatJson(parsedJson).array().isEmpty()''') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - "MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue("#652") @@ -1225,23 +1374,29 @@ DocumentContext parsedJson = JsonPath.parse(json); ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains(''':{}}''') test.contains("""assertThatJson(parsedJson).field("['value']").isEqualTo("{}")""") and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - "MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue("#727") @@ -1271,22 +1426,28 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains('''.isEmpty()''') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - "MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue("#727") @@ -1314,22 +1475,28 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains('''.isEmpty()''') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - "MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue("#892") @@ -1352,34 +1519,40 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompile(methodBuilderName, test) asserter(test) and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder | asserter - "MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent -> + methodBuilderName | methodBuilder | asserter + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | { String testContent -> assert testContent. - contains('''response.header('Content-Length') ==~ java.util.regex.Pattern.compile('([1-9]\\\\d*)')''') && testContent. - contains('''response.header('Content-Type') ==~ java.util.regex.Pattern.compile('^\\\\s*\\\\S[\\\\S\\\\s]*')'''); return true + contains('''response.header("Content-Length") ==~ java.util.regex.Pattern.compile('([1-9]\\\\d*)')''') && testContent. + contains('''response.header("Content-Type") ==~ java.util.regex.Pattern.compile('^\\\\s*\\\\S[\\\\S\\\\s]*')'''); return true } - "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent -> + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | { String testContent -> assert testContent. contains('''assertThat(response.header("Content-Type")).matches("^\\\\s*\\\\S[\\\\S\\\\s]*")''') && testContent. contains('''assertThat(response.header("Content-Length")).matches("([1-9]\\\\d*)")'''); return true } - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent -> + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | { String testContent -> assert testContent. - contains('''response.getHeaderString('Content-Length') ==~ java.util.regex.Pattern.compile('([1-9]\\\\d*)')''') && testContent. - contains('''response.getHeaderString('Content-Type') ==~ java.util.regex.Pattern.compile('^\\\\s*\\\\S[\\\\S\\\\s]*')'''); return true + contains('''response.getHeaderString("Content-Length") ==~ java.util.regex.Pattern.compile("([1-9]\\\\d*)")''') && testContent. + contains('''response.getHeaderString("Content-Type") ==~ java.util.regex.Pattern.compile("^\\\\s*\\\\S[\\\\S\\\\s]*")'''); return true } - "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } | { String testContent -> + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | { String testContent -> assert testContent. contains('''assertThat(response.getHeaderString("Content-Type")).matches("^\\\\s*\\\\S[\\\\S\\\\s]*")''') && testContent. contains('''assertThat(response.getHeaderString("Content-Length")).matches("([1-9]\\\\d*)")'''); return true @@ -1404,22 +1577,28 @@ DocumentContext parsedJson = JsonPath.parse(json); status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains('''[value:123]''') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - "MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue("#1052") @@ -1454,23 +1633,29 @@ response: tmpFile.text = yaml Contract contractDsl = new YamlContractConverter().convertFrom(tmpFile). first() - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains('''(1541609556000)''') test.contains('''(1541609556000L)''') and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - "MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue("#1049") @@ -1489,21 +1674,27 @@ response: body("1\n2\n3\n") } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - "MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } def 'should resolve headers from request correctly'() { @@ -1529,12 +1720,10 @@ response: } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - String test = blockBuilder.toString() SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) and: test.contains($/assertThatJson(parsedJson).field("['result']").isEqualTo("Don't worry/$) @@ -1542,11 +1731,19 @@ response: and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder - "MockMvcSpockMethodBuilder" | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - "JaxRsClientJUnitMethodBodyBuilder" | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilderSpec.groovy index a2c3e8fc57..79f6e3f29b 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MethodBuilderSpec.groovy @@ -1,10 +1,12 @@ package org.springframework.cloud.contract.verifier.builder + import spock.lang.Issue import spock.lang.Specification import org.springframework.cloud.contract.spec.Contract import org.springframework.cloud.contract.verifier.file.ContractMetadata +import org.springframework.cloud.contract.verifier.file.SingleContractMetadata class MethodBuilderSpec extends Specification { @@ -24,13 +26,15 @@ class MethodBuilderSpec extends Specification { } } } - ContractMetadata metadata = new ContractMetadata(null, false, 0, null, contractDsl) - when: File stubFile = new File("invalid-method:name.groovy") - String methodName = MethodBuilder.methodName(metadata, stubFile, contractDsl) + ContractMetadata metadata = new ContractMetadata(stubFile.toPath(), false, 0, null, contractDsl) + SingleContractMetadata singleContractMetadata = new SingleContractMetadata(contractDsl, metadata) + when: + + String methodName = new NameProvider().methodName(singleContractMetadata) then: - methodName == "invalid_method_name" + methodName == "validate_invalid_method_name" } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy index 18ddedc1a1..86f547d8f3 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderWithMatchersSpec.groovy @@ -24,7 +24,10 @@ import spock.lang.Specification import org.springframework.boot.test.rule.OutputCapture 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.dsl.wiremock.WireMockStubVerifier +import org.springframework.cloud.contract.verifier.file.ContractMetadata import org.springframework.cloud.contract.verifier.util.SyntaxChecker class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements WireMockStubVerifier { @@ -41,6 +44,40 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod( new SingleTestGenerator.GeneratedClassData("foo", "bar", new File(".").toPath()), "method") + @Shared + SingleTestGenerator.GeneratedClassData generatedClassData = + new SingleTestGenerator.GeneratedClassData("foo", "com.example", new File(".").toPath()) + + private String singleTestGenerator(Contract contractDsl) { + return new JavaTestGenerator() { + @Override + ClassBodyBuilder classBodyBuilder(BlockBuilder builder, GeneratedClassMetaData metaData, SingleMethodBuilder methodBuilder) { + return super.classBodyBuilder(builder, metaData, methodBuilder).field(new Field() { + @Override + boolean accept() { + return metaData.configProperties.testMode == TestMode.JAXRSCLIENT + } + + @Override + Field call() { + builder.addLine("WebTarget webTarget") + return this + } + }) + } + }.buildClass(properties, [contractMetadata(contractDsl)], "foo", generatedClassData) + } + + private ContractMetadata contractMetadata(Contract contractDsl) { + return new ContractMetadata(new File(".").toPath(), false, 0, null, contractDsl) + } + + def setup() { + properties = new ContractVerifierConfigProperties( + assertJsonSize: true + ) + } + @Issue('#185') def 'should allow to set dynamic values via stub / test matchers for [#methodBuilderName]'() { given: @@ -164,11 +201,9 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements } } //end::matchers[] - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThat(parsedJson.read("' + rootElement + '.duck", String.class)).matches("[0-9]{3}")') test.contains('assertThat(parsedJson.read("' + rootElement + '.duck", Integer.class)).isEqualTo(123)') @@ -200,7 +235,7 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements !test.contains('cursor') and: try { - SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) } catch (ClassFormatError classFormatError) { String output = outputCapture.toString() @@ -208,12 +243,18 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements assert output.contains('assertThatValueIsANumber(parsedJson.read("$.duck"));') } where: - methodBuilderName | methodBuilder | rootElement - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' + methodBuilderName | methodBuilder | rootElement + "spock" | { properties.testFramework = TestFramework.SPOCK } | '\\$' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '$' + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | '\\$' + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | '$' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | '$' } @Issue('#217') @@ -262,29 +303,33 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThat((java.lang.Iterable) parsedJson.read("' + rootElement + '.phoneNumbers[*].number", java.util.Collection.class)).as("' + rootElement + '.phoneNumbers[*].number").allElementsMatch("^[0-9]{3} [0-9]{3}-[0-9]{4}' + rootElement + '")') test.contains('assertThat((java.lang.Iterable) parsedJson.read("' + rootElement + '..number", java.util.Collection.class)).as("' + rootElement + '..number").allElementsMatch("^[0-9]{3} [0-9]{3}-[0-9]{4}' + rootElement + '")') !test.contains('cursor') and: try { - SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) } catch (NoClassDefFoundError error) { // that's actually expected since we're creating an anonymous class } where: - methodBuilderName | methodBuilder | rootElement - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' + methodBuilderName | methodBuilder | rootElement + "spock" | { properties.testFramework = TestFramework.SPOCK } | '\\$' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '$' + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | '\\$' + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | '$' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | '$' } @@ -317,11 +362,9 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThat((java.lang.Iterable) parsedJson.read("' + rootElement + '.phoneNumbers[*].number", java.util.Collection.class)).as("' + rootElement + '.phoneNumbers[*].number").hasFlattenedSizeBetween(0, 4)') test.contains('assertThat((java.lang.Iterable) parsedJson.read("' + rootElement + '.phoneNumbers[*].number", java.util.Collection.class)).as("' + rootElement + '.phoneNumbers[*].number").hasFlattenedSizeGreaterThanOrEqualTo(0)') @@ -329,18 +372,24 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements !test.contains('cursor') and: try { - SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) } catch (NoClassDefFoundError error) { // that's actually expected since we're creating an anonymous class } where: - methodBuilderName | methodBuilder | rootElement - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' + methodBuilderName | methodBuilder | rootElement + "spock" | { properties.testFramework = TestFramework.SPOCK } | '\\$' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '$' + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | '\\$' + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | '$' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | '$' } @Issue('#217') @@ -363,20 +412,24 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('foo(parsedJson.read("' + rootElement + '.phoneNumbers[*].number")') where: - methodBuilderName | methodBuilder | rootElement - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' + methodBuilderName | methodBuilder | rootElement + "spock" | { properties.testFramework = TestFramework.SPOCK } | '\\$' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '$' + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | '\\$' + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | '$' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | '$' } @Issue('#217') @@ -399,20 +452,25 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + singleTestGenerator(contractDsl) then: IllegalStateException e = thrown(IllegalStateException) e.message.contains('Entry for the provided JSON path <$.nonExistingPhoneNumbers[*].number> doesn\'t exist in the body') where: - methodBuilderName | methodBuilder | rootElement - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' + methodBuilderName | methodBuilder | rootElement + "spock" | { properties.testFramework = TestFramework.SPOCK } | '\\$' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '$' + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | '\\$' + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | '$' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | '$' } @Issue('#229') @@ -437,22 +495,25 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: + String test = singleTestGenerator(contractDsl) SyntaxChecker.tryToCompile(methodBuilderName, test) then: test.contains('assertThat(parsedJson.read("' + rootElement + '[0][0].access_token", String.class)).isEqualTo("123")') where: - methodBuilderName | methodBuilder | rootElement - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' + methodBuilderName | methodBuilder | rootElement + "spock" | { properties.testFramework = TestFramework.SPOCK } | '\\$' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '$' + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | '\\$' + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | '$' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | '$' } @Issue('#391') @@ -485,22 +546,25 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements headers { header 'content-type', 'application/...json;charset=UTF-8' } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: + String test = singleTestGenerator(contractDsl) SyntaxChecker.tryToCompile(methodBuilderName, test) then: !test.contains('''assertThatJson(parsedJson).array("['items']").isEmpty()''') where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#391') @@ -529,22 +593,25 @@ class MockMvcMethodBodyBuilderWithMatchersSpec extends Specification implements headers { header 'content-type', 'application/...json;charset=UTF-8' } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: + String test = singleTestGenerator(contractDsl) SyntaxChecker.tryToCompile(methodBuilderName, test) then: !test.contains('''assertThatJson(parsedJson).array("['items']").isEmpty()''') where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } } 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 b84303e48f..e02a3483d4 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 @@ -161,22 +161,22 @@ class SingleTestGeneratorSpec extends Specification { } response { status OK() + body(["foo" : "bar"]) } } ''') } - def 'should build test class for #testFramework'() { + def 'should build test class for #testFramework and mode #mode'() { given: ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() properties.testFramework = testFramework properties.testMode = mode ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, order, convertAsCollection(new File('/'), file)) - contract.ignored >> true JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract], 'test', 'test', 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract], 'com/foo', new SingleTestGenerator.GeneratedClassData('test', 'test', file.toPath())) then: classStrings.each { assert clazz.contains(it) } @@ -222,39 +222,6 @@ class SingleTestGeneratorSpec extends Specification { SPOCK | EXPLICIT | GROOVY_ASSERTER | 'ContractsSpec.groovy' } - def "should build test class for #testFramework with Rest Assured 2x"() { - given: - ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties() - properties.testFramework = testFramework - properties.testMode = mode - ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, order, - convertAsCollection(new File('/'), file)) - contract.ignored >> true - JavaTestGenerator testGenerator = new JavaTestGenerator(checker: new ClassPresenceChecker() { - @Override - boolean isClassPresent(String className) { - return true - } - }) - - when: - 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') - - where: - testFramework | order | mode | classStrings - JUNIT | 2 | MOCKMVC | mockMvcJUnitRestAssured2ClassStrings - JUNIT | 2 | EXPLICIT | explicitJUnitRestAssured2ClassStrings - JUNIT5 | null | MOCKMVC | mockMvcJUnit5RestAssured2ClassStrings - JUNIT5 | null | EXPLICIT | explicitJUnit5RestAssured2ClassStrings - SPOCK | 2 | MOCKMVC | spockClassRestAssured2Strings - SPOCK | 2 | EXPLICIT | explicitSpockRestAssured2ClassStrings - } - def 'should build test class for #testFramework and mode #mode with two files'() { given: File file = tmpFolder.newFile() @@ -310,7 +277,7 @@ class SingleTestGeneratorSpec extends Specification { JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract, contract2], 'test', 'test', 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract, contract2], 'com/foo', new SingleTestGenerator.GeneratedClassData('test', 'test', file.toPath())) then: classStrings.each { clazz.contains(it) } @@ -324,8 +291,8 @@ class SingleTestGeneratorSpec extends Specification { JUNIT | 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 | 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 | EXPLICIT | explicitSpockRestAssured2ClassStrings | GROOVY_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, '\t\t\tdef request') == 2 } + SPOCK | MOCKMVC | spockClassRestAssured3Strings | GROOVY_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification') == 2 } + SPOCK | EXPLICIT | explicitSpockRestAssured2ClassStrings | GROOVY_ASSERTER | { String test -> StringUtils.countOccurrencesOf(test, '\t\t\tMockMvcRequestSpecification request') == 2 } } def 'should build JaxRs test class for #testFramework'() { @@ -335,10 +302,10 @@ class SingleTestGeneratorSpec extends Specification { properties.testFramework = testFramework ContractMetadata contract = new ContractMetadata(file.toPath(), true, 1, null, convertAsCollection(new File('/'), file)) contract.ignored >> true - JavaTestGenerator testGenerator = new JavaTestGenerator() + SingleTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract], 'test', 'test', 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract], 'com/foo', new SingleTestGenerator.GeneratedClassData('test', 'test', file.toPath())) then: classStrings.each { clazz.contains(it) } @@ -384,7 +351,7 @@ class SingleTestGeneratorSpec extends Specification { JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract, contract2], 'test', 'test', 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract, contract2], 'com/foo', new SingleTestGenerator.GeneratedClassData('test', 'test', file.toPath())) then: classStrings.each { clazz.contains(it) } @@ -401,7 +368,7 @@ class SingleTestGeneratorSpec extends Specification { } @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 with #testFramework and ignore annotation #ignoreAnnotation'() { given: File secondFile = tmpFolder.newFile() secondFile.write(''' @@ -426,7 +393,7 @@ class SingleTestGeneratorSpec extends Specification { JavaTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract2], 'test', 'test', 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract2], 'com/foo', new SingleTestGenerator.GeneratedClassData('test', 'test', file.toPath())) then: classStrings.each { clazz.contains(it) } @@ -492,13 +459,13 @@ class SingleTestGeneratorSpec extends Specification { and: SingleTestGenerator testGenerator = new JavaTestGenerator() when: - String clazz = testGenerator.buildClass(properties, [contract], 'test', 'test', 'com/foo') + String clazz = testGenerator.buildClass(properties, [contract], 'com/foo', new SingleTestGenerator.GeneratedClassData('test', 'test', file.toPath())) then: clazz.contains('RequestSpecification request = given();') clazz.contains('Response response = given().spec(request)') } - def "should pick the contract's name as the test method"() { + def "should pick the contract's name as the test method for #testFramework"() { given: File secondFile = tmpFolder.newFile() secondFile.write(''' @@ -519,14 +486,14 @@ class SingleTestGeneratorSpec extends Specification { 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], 'com/foo', new SingleTestGenerator.GeneratedClassData('test', 'test', file.toPath())) then: clazz.contains('validate_mySuperMethod()') where: testFramework << [JUNIT, JUNIT5, SPOCK] } - def "should pick the contract's name as the test method when there are multiple contracts"() { + def "should pick the contract's name as the test method when there are multiple contracts for #testFramework"() { given: File secondFile = tmpFolder.newFile() secondFile.write(''' @@ -551,7 +518,7 @@ class SingleTestGeneratorSpec extends Specification { 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], 'com/foo', new SingleTestGenerator.GeneratedClassData('test', 'test', file.toPath())) then: clazz.contains('validate_shouldHaveIndex1()') clazz.contains('validate_shouldHaveIndex2()') @@ -559,7 +526,7 @@ class SingleTestGeneratorSpec extends Specification { 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 for #testFramework'() { given: File secondFile = tmpFolder.newFile() secondFile.write(''' @@ -583,7 +550,7 @@ class SingleTestGeneratorSpec extends Specification { 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], 'com/foo', new SingleTestGenerator.GeneratedClassData('test', 'test', file.toPath())) then: clazz.contains('_0() throws Exception') clazz.contains('_1() throws Exception') @@ -724,7 +691,7 @@ class SingleTestGeneratorSpec extends Specification { 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') + testGenerator.buildClass(properties, [contract], 'com/foo', new SingleTestGenerator.GeneratedClassData('test', 'test', file.toPath())) then: thrown(UnsupportedOperationException) where: diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy index d2b1456b71..b9df72fc06 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/SpringTestMethodBodyBuildersSpec.groovy @@ -18,7 +18,6 @@ package org.springframework.cloud.contract.verifier.builder import java.util.regex.Pattern -import org.codehaus.groovy.control.MultipleCompilationErrorsException import org.junit.Rule import spock.lang.Issue import spock.lang.Shared @@ -28,7 +27,10 @@ import spock.util.environment.RestoreSystemProperties import org.springframework.boot.test.rule.OutputCapture 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.dsl.wiremock.WireMockStubVerifier +import org.springframework.cloud.contract.verifier.file.ContractMetadata import org.springframework.cloud.contract.verifier.util.SyntaxChecker /** @@ -46,8 +48,8 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock ) @Shared - GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod( - new SingleTestGenerator.GeneratedClassData("foo", "bar", new File(".").toPath()), "method") + SingleTestGenerator.GeneratedClassData generatedClassData = + new SingleTestGenerator.GeneratedClassData("foo", "com.example", new File(".").toPath()) @Shared Contract contractDslWithCookiesValue = Contract.make { @@ -178,6 +180,12 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock } } + def setup() { + properties = new ContractVerifierConfigProperties( + assertJsonSize: true + ) + } + def 'should generate assertions for simple response body with #methodBuilderName'() { given: Contract contractDsl = Contract.make { @@ -193,22 +201,49 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock }""" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } + } + + private String singleTestGenerator(Contract contractDsl) { + return new JavaTestGenerator() { + @Override + ClassBodyBuilder classBodyBuilder(BlockBuilder builder, GeneratedClassMetaData metaData, SingleMethodBuilder methodBuilder) { + return super.classBodyBuilder(builder, metaData, methodBuilder).field(new Field() { + @Override + boolean accept() { + return metaData.configProperties.testMode == TestMode.JAXRSCLIENT + } + + @Override + Field call() { + builder.addLine("WebTarget webTarget") + return this + } + }) + } + }.buildClass(properties, [contractMetadata(contractDsl)], "foo", generatedClassData) + } + + private GeneratedClassMetaData generatedClassMetaData(Contract contractDsl) { + new GeneratedClassMetaData(properties, [contractMetadata(contractDsl)], "foo", generatedClassData) + } + + ContractMetadata contractMetadata(Contract contractDsl) { + return new ContractMetadata(new File(".").toPath(), false, 0, null, contractDsl) } @Issue('#187') @@ -228,23 +263,22 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock }""" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("true")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").isNull()""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property3']").isEqualTo(false)""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("true")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").isNull()""") + test.contains("""assertThatJson(parsedJson).field("['property3']").isEqualTo(false)""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#79') @@ -266,23 +300,22 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#79') @@ -306,24 +339,23 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").hasSize(2)""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").hasSize(2)""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#82') @@ -341,21 +373,24 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains(bodyString) + test.contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | """.body('''{\"items\":[\"HOP\"]}''')""" - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("{\\"items\\":[\\"HOP\\"]}")' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("{\\"items\\":[\\"HOP\\"]}")' + methodBuilderName | methodBuilder | bodyString + "spock" | { properties.testFramework = TestFramework.SPOCK } | """.body('''{\"items\":[\"HOP\"]}''')""" + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | '.body("{\\"items\\":[\\"HOP\\"]}")' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | '.body("{\\"items\\":[\\"HOP\\"]}")' } @Issue('#88') @@ -373,21 +408,20 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains(bodyString) + test.contains(bodyString) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder | bodyString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | """.body('''property1=VAL1''')""" - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("property1=VAL1")' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("property1=VAL1")' + methodBuilderName | methodBuilder | bodyString + "spock" | { properties.testFramework = TestFramework.SPOCK } | """.body('''property1=VAL1''')""" + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '.body("property1=VAL1")' + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } | '.body("property1=VAL1")' } @Issue('185') @@ -408,22 +442,21 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property']").field(7).isEqualTo(0.0)""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property']").field(14).isEqualTo(0.0)""") + test.contains("""assertThatJson(parsedJson).field("['property']").field(7).isEqualTo(0.0)""") + test.contains("""assertThatJson(parsedJson).field("['property']").field(14).isEqualTo(0.0)""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate assertions for array in response body with #methodBuilderName'() { @@ -444,22 +477,21 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock }]""" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("['property2']").isEqualTo("b")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).array().contains("['property2']").isEqualTo("b")""") + test.contains("""assertThatJson(parsedJson).array().contains("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate assertions for array inside response body element with #methodBuilderName'() { @@ -479,22 +511,21 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock }""" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property1']").contains("['property2']").isEqualTo("test1")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property1']").contains("['property3']").isEqualTo("test2")""") + test.contains("""assertThatJson(parsedJson).array("['property1']").contains("['property2']").isEqualTo("test1")""") + test.contains("""assertThatJson(parsedJson).array("['property1']").contains("['property3']").isEqualTo("test2")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate assertions for nested objects in response body with #methodBuilderName'() { @@ -514,22 +545,21 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock ''' } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").field("['property3']").isEqualTo("b")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").field("['property3']").isEqualTo("b")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate regex assertions for map objects in response body with #methodBuilderName'() { @@ -553,22 +583,21 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate regex assertions for string objects in response body with #methodBuilderName'() { @@ -588,22 +617,21 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").matches("[0-9]{3}")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue(['#126', '#143']) @@ -624,21 +652,20 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property']").matches("\\\\d+")""") + test.contains("""assertThatJson(parsedJson).field("['property']").matches("\\\\d+")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate a call with an url path and query parameters with #methodBuilderName'() { @@ -671,11 +698,9 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock """ } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''.queryParam("limit","10")''') test.contains('''.queryParam("offset","20")''') @@ -691,12 +716,12 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#169') @@ -730,11 +755,9 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock """ } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''.queryParam("limit","10")''') test.contains('''.queryParam("offset","20")''') @@ -750,12 +773,12 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate test for empty body with #methodBuilderName'() { @@ -770,22 +793,20 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock status 406 } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ".body('''''')" - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("")' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("")' + methodBuilderName | methodBuilder | bodyString + "spock" | { properties.testFramework = TestFramework.SPOCK } | ".body('''''')" + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '.body("")' + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } | '.body("")' } def 'should generate test for String in response body with #methodBuilderName'() { @@ -800,23 +821,27 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock body 'test' } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(bodyDefinitionString) test.contains(bodyEvaluationString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'def responseBody = (response.body.asString())' | 'responseBody == "test"' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'String responseBody = response.getBody().asString();' | 'assertThat(responseBody).isEqualTo("test");' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'String responseBody = response.getBody().asString();' | 'assertThat(responseBody).isEqualTo("test");' + methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | 'String responseBody = response.body.asString()' | "responseBody == 'test'" + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | 'String responseBody = response.getBody().asString();' | 'assertThat(responseBody).isEqualTo("test");' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | 'String responseBody = response.getBody().asString();' | 'assertThat(responseBody).isEqualTo("test");' } @Issue('113') @@ -843,22 +868,24 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(headerEvaluationString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | headerEvaluationString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''response.header('Location') ==~ java.util.regex.Pattern.compile('http://localhost/partners/[0-9]+/users/[0-9]+')''' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'assertThat(response.header("Location")).matches("http://localhost/partners/[0-9]+/users/[0-9]+");' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'assertThat(response.header("Location")).matches("http://localhost/partners/[0-9]+/users/[0-9]+");' + methodBuilderName | methodBuilder | headerEvaluationString + "spock" | { properties.testFramework = TestFramework.SPOCK } | '''response.header("Location") ==~ java.util.regex.Pattern.compile('http://localhost/partners/[0-9]+/users/[0-9]+')''' + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | 'assertThat(response.header("Location")).matches("http://localhost/partners/[0-9]+/users/[0-9]+");' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | 'assertThat(response.header("Location")).matches("http://localhost/partners/[0-9]+/users/[0-9]+");' } @Issue('115') @@ -885,22 +912,24 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(headerEvaluationString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | headerEvaluationString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''response.header('Location') ==~ java.util.regex.Pattern.compile('^((http[s]?|ftp):/)/?([^:/\\\\s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+')''' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'assertThat(response.header("Location")).matches("^((http[s]?|ftp):/)/?([^:/\\\\s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+");' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'assertThat(response.header("Location")).matches("^((http[s]?|ftp):/)/?([^:/\\\\s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+");' + methodBuilderName | methodBuilder | headerEvaluationString + "spock" | { properties.testFramework = TestFramework.SPOCK } | '''response.header("Location") ==~ java.util.regex.Pattern.compile('^((http[s]?|ftp):/)/?([^:/\\\\s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+')''' + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | 'assertThat(response.header("Location")).matches("^((http[s]?|ftp):/)/?([^:/\\\\s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+");' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | 'assertThat(response.header("Location")).matches("^((http[s]?|ftp):/)/?([^:/\\\\s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+");' } def 'should work with more complex stuff and jsonpaths with #methodBuilderName'() { @@ -928,23 +957,21 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock ]) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains("""assertThatJson(parsedJson).array("['errors']").contains("['property']").isEqualTo("bank_account_number")""") test.contains("""assertThatJson(parsedJson).array("['errors']").contains("['message']").isEqualTo("incorrect_format")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should work properly with GString url with #methodBuilderName'() { @@ -965,22 +992,20 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock status 422 } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''/partners/11/agents/11/customers/09665703Z''') and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should resolve properties in GString with regular expression with #methodBuilderName'() { @@ -1009,31 +1034,27 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains("""assertThatJson(parsedJson).field("['message']").matches("User not found by email = \\\\\\\\[[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\\\\\\\.[a-zA-Z]{2,6}\\\\\\\\]")""") and: // no static compilation due to bug in Groovy https://issues.apache.org/jira/browse/GROOVY-8055 - SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('42') def 'should not omit the optional field in the test creation with MockMvcSpockMethodBodyBuilder'() { given: - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''"email":"abc@abc.com"''') test.contains("""assertThatJson(parsedJson).field("['code']").matches("(123123)?")""") @@ -1041,19 +1062,15 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock !test.contains('''OPTIONAL''') !test.contains('''OptionalProperty''') and: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileGroovy("spock", test) where: contractDsl << [dslWithOptionals, dslWithOptionalsInString] } @Issue('42') def "should not omit the optional field in the test creation with MockMvcJUnitMethodBodyBuilder"() { - given: - MethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('\\"email\\":\\"abc@abc.com\\"') test.contains('assertThatJson(parsedJson).field("[\'code\']").matches("(123123)?");') @@ -1061,7 +1078,7 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock !test.contains('''OPTIONAL''') !test.contains('''OptionalProperty''') and: - SyntaxChecker.tryToCompileJava(MockMvcJUnitMethodBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileJava("mockmvc", test) where: contractDsl << [dslWithOptionals, dslWithOptionalsInString] } @@ -1104,20 +1121,24 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: assertionStrings.each { String assertionString -> assert test.contains(assertionString) } where: - methodBuilderName | methodBuilder | assertionStrings - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['''assertThatRejectionReasonIsNull(parsedJson.read(\'\'\'$.rejectionReason\'\'\'))''', '''assertThatLocationIsNull(response.header('Location'))'''] - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] + methodBuilderName | methodBuilder | assertionStrings + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | ['''assertThatRejectionReasonIsNull(parsedJson.read("\\$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] } def 'should support inner map and list definitions with #methodBuilderName'() { @@ -1172,22 +1193,20 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains bodyString !test.contains("clientValue") !test.contains("cursor") and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '"street":"Light Street"' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\"street\\":\\"Light Street\\"' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\"street\\":\\"Light Street\\"' + methodBuilderName | methodBuilder | bodyString + "spock" | { properties.testFramework = TestFramework.SPOCK } | '"street":"Light Street"' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '\\"street\\":\\"Light Street\\"' + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } | '\\"street\\":\\"Light Street\\"' } @@ -1211,35 +1230,16 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) - and: - String jsonSample = '''\ -String json = "{\\"code\\":null}"; -DocumentContext parsedJson = JsonPath.parse(json); -''' - and: - LinkedList lines = [] as LinkedList - test.eachLine { - if (it.contains("assertThatJson")) { - lines << it - } - else { - it - } - } - lines.addFirst(jsonSample) - SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n")) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '"street":"Light Street"' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\"street\\":\\"Light Street\\"' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\"street\\":\\"Light Street\\"' + methodBuilderName | methodBuilder | bodyString + "spock" | { properties.testFramework = TestFramework.SPOCK } | '"street":"Light Street"' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '\\"street\\":\\"Light Street\\"' + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } | '\\"street\\":\\"Light Street\\"' } @@ -1268,20 +1268,18 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains("\\u041f") and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('177') @@ -1298,21 +1296,19 @@ World.''') status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.given(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(bodyString) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | """'''hello, + methodBuilderName | methodBuilder | bodyString + "spock" | { properties.testFramework = TestFramework.SPOCK } | """'''hello, World.'''""" - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '"hello,\\nWorld."' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '"hello,\\nWorld."' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '"hello,\\nWorld."' + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } | '"hello,\\nWorld."' } @Issue('180') @@ -1346,31 +1342,35 @@ World.'''""" } } // end::multipartdsl[] - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: for (String requestString : requestStrings) { assert test.contains(requestString) } and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | requestStrings - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - """.param('formParameter', '"formParameterValue"'""", - """.param('someBooleanParameter', 'true')""", - """.multiPart('file', 'filename.csv', 'file content'.bytes, 'application/json')"""] - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.param("formParameter", "\\"formParameterValue\\"")', - '.param("someBooleanParameter", "true")', - '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.param("formParameter", "\\"formParameterValue\\"")', - '.param("someBooleanParameter", "true")', - '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] + methodBuilderName | methodBuilder | requestStrings + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + """.param('formParameter', '''"formParameterValue"'''""", + """.param('someBooleanParameter', 'true')""", + """.multiPart('file', 'filename.csv', 'file content'.bytes, 'application/json')"""] + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.param("formParameter", "\\"formParameterValue\\"")', + '.param("someBooleanParameter", "true")', + '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.param("formParameter", "\\"formParameterValue\\"")', + '.param("someBooleanParameter", "true")', + '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] } @@ -1401,31 +1401,35 @@ World.'''""" status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: for (String requestString : requestStrings) { assert test.contains(requestString) } and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | requestStrings - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - """.param('formParameter', '"formParameterValue"'""", - """.param('someBooleanParameter', 'true')""", - """.multiPart('file', 'filename.csv', 'file content'.bytes)"""] - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.param("formParameter", "\\"formParameterValue\\"")', - '.param("someBooleanParameter", "true")', - '.multiPart("file", "filename.csv", "file content".getBytes());'] - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.param("formParameter", "\\"formParameterValue\\"")', - '.param("someBooleanParameter", "true")', - '.multiPart("file", "filename.csv", "file content".getBytes());'] + methodBuilderName | methodBuilder | requestStrings + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + """.param('formParameter', '''"formParameterValue"'''""", + """.param('someBooleanParameter', 'true')""", + """.multiPart('file', 'filename.csv', 'file content'.bytes)"""] + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.param("formParameter", "\\"formParameterValue\\"")', + '.param("someBooleanParameter", "true")', + '.multiPart("file", "filename.csv", "file content".getBytes());'] + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.param("formParameter", "\\"formParameterValue\\"")', + '.param("someBooleanParameter", "true")', + '.multiPart("file", "filename.csv", "file content".getBytes());'] } @Issue('546') @@ -1451,25 +1455,29 @@ World.'''""" } } // end::multipartdsl[] - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: for (String requestString : requestStrings) { assert test.contains(requestString) } and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | requestStrings - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - """.multiPart('file', 'file', [100, 117, 100, 97] as byte[])"""] - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.multiPart("file", "file", new byte[] {100, 117, 100, 97});'] - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.multiPart("file", "file", new byte[] {100, 117, 100, 97});'] + methodBuilderName | methodBuilder | requestStrings + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + """.multiPart('file', 'file', [100, 117, 100, 97] as byte[])"""] + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.multiPart("file", "file", new byte[] {100, 117, 100, 97});'] + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.multiPart("file", "file", new byte[] {100, 117, 100, 97});'] } @@ -1495,31 +1503,35 @@ World.'''""" status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: for (String requestString : requestStrings) { assert test.contains(requestString) } and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | requestStrings - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - """.param('formParameter', '"formParameterValue"'""", - """.param('someBooleanParameter', 'true')""", - """.multiPart('file', toString(), 'file content'.bytes)"""] - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.param("formParameter", "\\"formParameterValue\\"")', - '.param("someBooleanParameter", "true")', - '.multiPart("file", toString(), "file content".getBytes());'] - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.param("formParameter", "\\"formParameterValue\\"")', - '.param("someBooleanParameter", "true")', - '.multiPart("file", toString(), "file content".getBytes());'] + methodBuilderName | methodBuilder | requestStrings + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + """.param('formParameter', '''"formParameterValue"'''""", + """.param('someBooleanParameter', 'true')""", + """.multiPart('file', toString(), 'file content'.bytes)"""] + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.param("formParameter", "\\"formParameterValue\\"")', + '.param("someBooleanParameter", "true")', + '.multiPart("file", toString(), "file content".getBytes());'] + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.param("formParameter", "\\"formParameterValue\\"")', + '.param("someBooleanParameter", "true")', + '.multiPart("file", toString(), "file content".getBytes());'] } @@ -1550,20 +1562,18 @@ World.'''""" status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.given(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('.multiPart') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#216') @@ -1590,15 +1600,13 @@ World.'''""" ) } } - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''assertThatJson(parsedJson).array("[\'authorities']").arrayField().matches("^[a-zA-Z0-9_\\\\- ]+\\$").value()''') and: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#216') @@ -1625,15 +1633,12 @@ World.'''""" ) } } - MethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''assertThatJson(parsedJson).array("[\'authorities']").arrayField().matches("^[a-zA-Z0-9_\\\\- ]+$").value()''') and: - SyntaxChecker.tryToCompileJava(MockMvcJUnitMethodBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileJava("mockmvc", test) } def 'should work with execution property with #methodBuilderName'() { @@ -1652,19 +1657,17 @@ World.'''""" } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('''assertThatJson(parsedJson).field("[\'rejectionReason']").isEqualTo("assertThatRejectionReasonIsNull("''') test.contains('''assertThatRejectionReasonIsNull(''') where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('262') @@ -1689,15 +1692,13 @@ World.'''""" } } } - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).array().contains("[\'id\']").matches("[0-9]+")') and: - SyntaxChecker.tryToCompileGroovy(MockMvcJUnitMethodBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileGroovy("mockmvc", test) } @Issue('266') @@ -1716,11 +1717,9 @@ World.'''""" } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).arrayField().contains("Java8").value()') test.contains('assertThatJson(parsedJson).arrayField().contains("Spring").value()') @@ -1728,12 +1727,12 @@ World.'''""" test.contains('assertThatJson(parsedJson).arrayField().contains("Stream").value()') test.contains('assertThatJson(parsedJson).arrayField().contains("SpringBoot").value()') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('266') @@ -1754,11 +1753,9 @@ World.'''""" } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).hasSize(5)') test.contains('assertThatJson(parsedJson).arrayField().contains("Java8").value()') @@ -1767,12 +1764,12 @@ World.'''""" test.contains('assertThatJson(parsedJson).arrayField().contains("Stream").value()') test.contains('assertThatJson(parsedJson).arrayField().contains("SpringBoot").value()') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('266') @@ -1791,23 +1788,21 @@ World.'''""" } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).array().array().arrayField().isEqualTo("Programming").value()') test.contains('assertThatJson(parsedJson).array().array().arrayField().isEqualTo("Java").value()') test.contains('assertThatJson(parsedJson).array().array().arrayField().isEqualTo("Spring").value()') test.contains('assertThatJson(parsedJson).array().array().arrayField().isEqualTo("Boot").value()') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('47') @@ -1823,21 +1818,19 @@ World.'''""" async() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(bodyDefinitionString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyDefinitionString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.when().async()' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.when().async()' + methodBuilderName | methodBuilder | bodyDefinitionString + "spock" | { properties.testFramework = TestFramework.SPOCK } | '.when().async()' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '.when().async()' } @Issue('372') @@ -1857,22 +1850,20 @@ World.'''""" async() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() - def strippedTest = test.replace('\n', '').replace(' ', '').stripIndent().stripMargin() + String test = singleTestGenerator(contractDsl) + def strippedTest = test.replace('\n', '').replace(' ', '').replaceAll("\t", "").stripIndent().stripMargin() then: strippedTest.contains('.queryParam("param","value").when().async().get("/test")') and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } } def 'should generate proper test code with array of primitives using #methodBuilderName'() { @@ -1894,21 +1885,19 @@ World.'''""" ''') } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).array("[\'partners\']").array("[\'payment_methods\']").arrayField().isEqualTo("BANK").value()') test.contains('assertThatJson(parsedJson).array("[\'partners\']").array("[\'payment_methods\']").arrayField().isEqualTo("CASH").value()') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#273') @@ -1924,15 +1913,14 @@ World.'''""" body(code: 9, message: $(consumer('Wrong credentials'), producer(regex('^(?!\\s*$).+')))) } } - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).field("[\'message\']").matches("^(?!\\\\s*\\$).+")') and: - SyntaxChecker.tryToCompileGroovy(MockMvcJUnitMethodBodyBuilder.simpleName, blockBuilder.toString(), false) + SyntaxChecker.tryToCompileGroovy("mockmvc", test, false) } Contract dslForDocs = @@ -2009,22 +1997,19 @@ World.'''""" @Issue('#32') def 'should generate the regular expression for the other side of communication'() { given: - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder( - dslWithOnlyOneSideForDocs, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(dslWithOnlyOneSideForDocs) def strippedTest = test.replace('\n', '').stripIndent().stripMargin() then: strippedTest.matches(""".*header\\("header", "application\\/vnd\\.fraud\\.v1\\+json;.*"\\).*""") strippedTest.matches(""".*body\\('''\\{"requestElement":"[0-9]{5}"\\}'''\\).*""") strippedTest.matches(""".*put\\("/foo/[0-9]{5}"\\).*""") - strippedTest.contains("""response.header('Content-Type') ==~ java.util.regex.Pattern.compile('application/vnd\\\\.fraud\\\\.v1\\\\+json.*')""") + strippedTest.contains("""response.header("Content-Type") ==~ java.util.regex.Pattern.compile('application/vnd\\\\.fraud\\\\.v1\\\\+json.*')""") "application/vnd.fraud.v1+json;charset=UTF-8".matches('application/vnd\\.fraud\\.v1\\+json.*') strippedTest.contains("""assertThatJson(parsedJson).field("['responseElement']").matches("[0-9]{7}")""") and: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#85') @@ -2045,18 +2030,13 @@ World.'''""" ]) } } - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.then(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: - test.contains('assertThatRejectionReasonIsNull(parsedJson.read(\'\'\'$.rejectionReason.title\'\'\'))') - when: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) - then: - def e = thrown(MultipleCompilationErrorsException) - e.message.contains("Cannot find matching method Script1#assertThatRejectionReasonIsNull") + test.contains('assertThatRejectionReasonIsNull(parsedJson.read("\\$.rejectionReason.title"))') + and: + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#85') @@ -2079,14 +2059,14 @@ World.'''""" ]) } } - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.then(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: - test.contains('''assertThatUserNameIsNotNull(parsedJson.read(\'\'\'$.[0].name\'\'\')''') - test.contains('''assertThatUserNameIsNotNull(parsedJson.read(\'\'\'$.[1].name\'\'\')''') + test.contains('''assertThatUserNameIsNotNull(parsedJson.read("\\$.[0].name")''') + test.contains('''assertThatUserNameIsNotNull(parsedJson.read("\\$.[1].name")''') + and: + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#85') @@ -2109,11 +2089,8 @@ World.'''""" ]) } } - MethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") when: - builder.then(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[0].name")''') test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$.[1].name")''') @@ -2140,18 +2117,13 @@ World.'''""" ]) } } - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.given(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('.header("authorization", getOAuthTokenHeader())') - when: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) - then: - def e = thrown(MultipleCompilationErrorsException) - e.message.contains("Cannot find matching method Script1#getOAuthTokenHeader") + and: + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#150') @@ -2167,15 +2139,14 @@ World.'''""" body(value(stub("HELLO FROM STUB"), server(regex(".*")))) } } - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + + String test = singleTestGenerator(contractDsl) then: test.contains("responseBody ==~ java.util.regex.Pattern.compile('.*')") and: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#150') @@ -2191,18 +2162,14 @@ World.'''""" body(value(stub("HELLO FROM STUB"), server(execute('foo($it)')))) } } - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + + String test = singleTestGenerator(contractDsl) then: test.contains("foo(responseBody)") - when: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) - then: - def e = thrown(MultipleCompilationErrorsException) - e.message.contains("Cannot find matching method Script1#foo") + and: + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#149') @@ -2226,18 +2193,13 @@ World.'''""" ]) } } - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.given(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('.header("authorization", getOAuthTokenHeader())') - when: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) - then: - def e = thrown(MultipleCompilationErrorsException) - e.message.contains("Cannot find matching method Script1#getOAuthTokenHeader()") + and: + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#149') @@ -2301,11 +2263,9 @@ World.'''""" } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).field("[\'aBoolean\']").matches("(true|false)")') test.contains('assertThatJson(parsedJson).field("[\'alpha\']").matches("[\\\\p{L}]*")') @@ -2329,29 +2289,17 @@ World.'''""" !test.contains('cursor') !test.contains('REGEXP>>') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) and: String jsonSample = '''\ String json = "{\\"duck\\":\\"8\\",\\"alpha\\":\\"YAJEOWYGMFBEWPMEMAZI\\",\\"number\\":-2095030871,\\"anInteger\\":1780305902,\\"positiveInt\\":345,\\"aDouble\\":42.345,\\"aBoolean\\":true,\\"ip\\":\\"129.168.99.100\\",\\"hostname\\":\\"https://foo389886219.com\\",\\"email\\":\\"foo@bar1367573183.com\\",\\"url\\":\\"https://foo-597104692.com\\",\\"httpsUrl\\":\\"https://baz-486093581.com\\",\\"uuid\\":\\"e436b817-b764-49a2-908e-967f2f99eb9f\\",\\"date\\":\\"2014-04-14\\",\\"dateTime\\":\\"2011-01-11T12:23:34\\",\\"time\\":\\"12:20:30\\",\\"iso8601WithOffset\\":\\"2015-05-15T12:23:34.123Z\\",\\"nonBlankString\\":\\"EPZWVIRHSUAPBJMMQSFO\\",\\"nonEmptyString\\":\\"RVMFDSEQFHRQFVUVQPIA\\",\\"anyOf\\":\\"foo\\"}"; DocumentContext parsedJson = JsonPath.parse(json); ''' - and: - LinkedList lines = [] as LinkedList - test.eachLine { - if (it.contains("assertThatJson")) { - lines << it - } - else { - it - } - } - lines.addFirst(jsonSample) - SyntaxChecker.tryToRun(methodBuilderName, lines.join("\n")) where: - methodBuilderName | methodBuilder | endOfLineRegExSymbol - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '\\$' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '$' + methodBuilderName | methodBuilder | endOfLineRegExSymbol + "spock" | { properties.testFramework = TestFramework.SPOCK } | '\\$' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '$' + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } | '$' } @Issue('#162') @@ -2372,20 +2320,18 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('application/vnd\\\\.fraud\\\\.v1\\\\+json.*') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#173') @@ -2409,21 +2355,19 @@ DocumentContext parsedJson = JsonPath.parse(json); status(200) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('org.springframework.cloud.contract.spec.internal.OptionalProperty') test.contains('(([0-9]{1,10}))?') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#172') @@ -2442,22 +2386,20 @@ DocumentContext parsedJson = JsonPath.parse(json); } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('assertThatJson(parsedJson).field("[\'a\']").isEqualTo(1)') test.contains(expectedAssertion) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: //order is inverted cause Intellij didn't parse this properly - methodBuilderName | methodBuilder | expectedAssertion - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''responseBody == "{\\"a\\":1}\\n{\\"a\\":2}"''' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' + methodBuilderName | methodBuilder | expectedAssertion + "spock" | { properties.testFramework = TestFramework.SPOCK } | """responseBody == '''{"a":1}\\n{"a":2}'''""" + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' } @Issue('#443') @@ -2478,22 +2420,30 @@ DocumentContext parsedJson = JsonPath.parse(json); ) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: testAssertion(test) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | testAssertion - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String testContents -> testContents.contains("""responseBody ==~ java.util.regex.Pattern.compile('true|false')""") } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String testContents -> testContents.contains("""responseBody ==~ java.util.regex.Pattern.compile('true|false')""") } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } + methodBuilderName | methodBuilder | testAssertion + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | { String testContents -> testContents.contains("""responseBody ==~ java.util.regex.Pattern.compile('true|false')""") } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | { String testContents -> testContents.contains("""responseBody ==~ java.util.regex.Pattern.compile("true|false")""") } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } } @Issue('#169') @@ -2516,21 +2466,19 @@ DocumentContext parsedJson = JsonPath.parse(json); headers { header('Content-Type': 'application/json;charset=UTF-8') } } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).field("[\'bar\']").matches("some value \\"with quote\\"|bar")') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: //order is inverted cause Intellij didn't parse this properly - methodBuilderName | methodBuilder | expectedAssertion - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''responseBody == "{\\"a\\":1}\\n{\\"a\\":2}"''' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' + methodBuilderName | methodBuilder | expectedAssertion + "spock" | { properties.testFramework = TestFramework.SPOCK } | '''responseBody == "{\\"a\\":1}\\n{\\"a\\":2}"''' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' } @Issue('#169') @@ -2539,33 +2487,38 @@ DocumentContext parsedJson = JsonPath.parse(json); Contract contractDsl = Contract.make { request { method 'POST' - url $(c("foo"), p(execute("executedMethod()"))) + url $(c("foo"), p(execute("toString()"))) } response { status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: - SyntaxChecker.tryToCompile(methodBuilderName, test) + String test = singleTestGenerator(contractDsl) then: - def e = thrown(Throwable) - missingMethodAssertion(e, capture) + SyntaxChecker.tryToCompile(methodBuilderName, test) and: - test.contains("executedMethod()") - !test.contains("\"executedMethod()\"") - !test.contains("'executedMethod()'") + test.contains("toString()") + !test.contains("\"toString()\"") + !test.contains("'toString()'") where: - methodBuilderName | methodBuilder | missingMethodAssertion - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { Throwable t, OutputCapture capture -> t.message.contains("Cannot find matching method Script1#executedMethod") } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { Throwable t, OutputCapture capture -> t.message.contains("Truncated class file") && capture.toString().contains("post(executedMethod())") } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { Throwable t, OutputCapture capture -> t.message.contains("Cannot find matching method Script1#executedMethod") } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { Throwable t, OutputCapture capture -> t.message.contains("Truncated class file") && capture.toString().contains("path(executedMethod())") } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { Throwable t, OutputCapture capture -> t.message.contains("Truncated class file") && capture.toString().contains("post(executedMethod())") } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#203') @@ -2585,23 +2538,24 @@ DocumentContext parsedJson = JsonPath.parse(json); ]) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: - SyntaxChecker.tryToCompile(methodBuilderName, test) + String test = singleTestGenerator(contractDsl) then: + SyntaxChecker.tryToCompile(methodBuilderName, test) test.contains('assertThatJson(parsedJson).array("[\'list\']").isEmpty()') !test.contains('assertThatJson(parsedJson).array("[\'foo\']").isEmpty()') where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#226') @@ -2618,23 +2572,30 @@ DocumentContext parsedJson = JsonPath.parse(json); body(12000) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: - SyntaxChecker.tryToCompile(methodBuilderName, test) + String test = singleTestGenerator(contractDsl) then: + SyntaxChecker.tryToCompile(methodBuilderName, test) requestAssertion(test) responseAssertion(test) where: - methodBuilderName | methodBuilder | requestAssertion | responseAssertion - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains("body('''12000''')") } | { String body -> body.contains('responseBody == "12000"') } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains('body("12000")') } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000");') } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains(""".method('GET', entity('12000', 'text/plain'))""") } | { String body -> body.contains('responseBody == "12000"') } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains(""".method("GET", entity("12000", "text/plain"))""") } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000")') } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains('body("12000")') } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000");') } + methodBuilderName | methodBuilder | requestAssertion | responseAssertion + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | { String body -> body.contains("body('''12000''')") } | { String body -> body.contains("responseBody == '12000'") } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | { String body -> body.contains('body("12000")') } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000");') } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | { String body -> body.contains(""".build("GET", entity("12000", "text/plain"))""") } | { String body -> body.contains('responseBody == "12000"') } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | { String body -> body.contains(""".build("GET", entity("12000", "text/plain"))""") } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000")') } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | { String body -> body.contains('body("12000")') } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000");') } } @Issue('#230') @@ -2687,14 +2648,11 @@ DocumentContext parsedJson = JsonPath.parse(json); } } //end::template_contract[] - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: - SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) + String test = singleTestGenerator(contractDsl) then: + SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains('''DslProperty''') !test.contains('''ERROR: ''') test.contains('''assertThatJson(parsedJson).field("['url']").isEqualTo("/api/v1/xxxx?foo=bar&foo=bar2")''') @@ -2720,12 +2678,22 @@ DocumentContext parsedJson = JsonPath.parse(json); test.contains('''assertThatJson(parsedJson).field("['rawParam']").isEqualTo("bar")''') responseAssertion(test) where: - methodBuilderName | methodBuilder | responseAssertion - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains("response.header('Authorization') == 'foo secret bar'") } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains('assertThat(response.header("Authorization")).isEqualTo("foo secret bar");') } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains("response.getHeaderString('Authorization') == 'foo secret bar'") } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains('assertThat(response.getHeaderString("Authorization")).isEqualTo("foo secret bar");') } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains('assertThat(response.header("Authorization")).isEqualTo("foo secret bar");') } + methodBuilderName | methodBuilder | responseAssertion + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | { String body -> body.contains("""response.header("Authorization") == 'foo secret bar'""") } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | { String body -> body.contains('assertThat(response.header("Authorization")).isEqualTo("foo secret bar");') } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | { String body -> body.contains('''response.getHeaderString("Authorization") == "foo secret bar"''') } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | { String body -> body.contains('assertThat(response.getHeaderString("Authorization")).isEqualTo("foo secret bar");') } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | { String body -> body.contains('''assertThat(response.header("Authorization")).isEqualTo("foo secret bar");''') } } @Issue('#230') @@ -2762,131 +2730,121 @@ DocumentContext parsedJson = JsonPath.parse(json); } } //end::template_contract[] - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: - SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) + String test = singleTestGenerator(contractDsl) then: + SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) !test.contains('''DslProperty''') test.contains('''assertThatJson(parsedJson).field("['responseFoo']").isEqualTo("bar")''') test.contains('''assertThatJson(parsedJson).field("['responseBaz']").isEqualTo(5)''') test.contains('''assertThatJson(parsedJson).field("['responseBaz2']").isEqualTo("Bla bla bar bla bla")''') where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate JUnit assertions with cookies [#methodBuilderName]'() { given: - MethodBodyBuilder builder = methodBuilder(contractDslWithCookiesValue) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithCookiesValue) then: test.contains('''.cookie("cookie-key", "cookie-value")''') - test.contains('''assertThat(response.getCookie("cookie-key")).isNotNull();''') - test.contains('''assertThat(response.getCookie("cookie-key")).isEqualTo("new-cookie-value");''') + test.contains('''assertThat(response.cookie("cookie-key")).isNotNull();''') + test.contains('''assertThat(response.cookie("cookie-key")).isEqualTo("new-cookie-value");''') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate JUnit assertions with cookies pattern [#methodBuilderName]'() { given: - MethodBodyBuilder builder = methodBuilder(contractDslWithCookiesPattern) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithCookiesPattern) then: !test.contains('''.cookie("cookie-key", "[A-Za-z]+")''') test.contains('''.cookie("cookie-key", "''') - test.contains('''assertThat(response.getCookie("cookie-key")).isNotNull();''') - test.contains('''assertThat(response.getCookie("cookie-key")).matches("[A-Za-z]+");''') + test.contains('''assertThat(response.cookie("cookie-key")).isNotNull();''') + test.contains('''assertThat(response.cookie("cookie-key")).matches("[A-Za-z]+");''') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should not generate JUnit cookie assertion with absent cookie [#methodBuilderName]'() { given: - MethodBodyBuilder builder = methodBuilder(contractDslWithAbsentCookies) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithAbsentCookies) then: !test.contains('cookie') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate spock assertions with cookies'() { given: - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDslWithCookiesValue, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithCookiesValue) then: test.contains('''.cookie("cookie-key", "cookie-value")''') - test.contains('''response.cookie('cookie-key') != null''') - test.contains('''response.cookie('cookie-key') == 'new-cookie-value''') + test.contains('''response.cookie("cookie-key") != null''') + test.contains('''response.cookie("cookie-key") == 'new-cookie-value''') and: - SyntaxChecker.tryToCompile(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompile("spock", test) } def 'should generate spock assertions with cookies pattern'() { given: - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDslWithCookiesPattern, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithCookiesPattern) then: !test.contains('''.cookie("cookie-key", "[A-Za-z]+")''') test.contains('''.cookie("cookie-key", "''') - test.contains('''response.cookie('cookie-key') != null''') - test.contains('''response.cookie('cookie-key') ==~ java.util.regex.Pattern.compile('[A-Za-z]+')''') + test.contains('''response.cookie("cookie-key") != null''') + test.contains('''response.cookie("cookie-key") ==~ java.util.regex.Pattern.compile('[A-Za-z]+')''') and: - SyntaxChecker.tryToCompile(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompile("spock", test) } def 'should not generate spock cookie assertion with absent cookie'() { given: - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDslWithAbsentCookies, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDslWithAbsentCookies) then: !test.contains("cookie") and: - SyntaxChecker.tryToCompile(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompile("spock", test) } @Issue('#554') def 'should create an assertion for an empty map or Object for [#methodBuilderName]'() { given: Contract contractDsl = Contract.make { + name("method") request { method 'GET' url '/api/v1/xxxx' @@ -2899,22 +2857,23 @@ DocumentContext parsedJson = JsonPath.parse(json); ]) } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: - SyntaxChecker.tryToRun(methodBuilderName, test.join("\n")) + String test = singleTestGenerator(contractDsl) then: + SyntaxChecker.tryToCompile(methodBuilderName, test) test.contains('''assertThatJson(parsedJson).field("['aMap']").field("['foo']").isEqualTo("bar")''') test.contains('''assertThatJson(parsedJson).field("['anEmptyMap']").isEmpty()''') where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/XmlMethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/XmlMethodBodyBuilderSpec.groovy index ce90d717ba..43bc79eed4 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/XmlMethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/XmlMethodBodyBuilderSpec.groovy @@ -24,6 +24,9 @@ import spock.lang.Unroll import org.springframework.boot.test.rule.OutputCapture 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.SyntaxChecker /** @@ -35,19 +38,50 @@ class XmlMethodBodyBuilderSpec extends Specification { @Rule OutputCapture capture = new OutputCapture() - @Shared - GeneratedClassDataForMethod classDataForMethod = new GeneratedClassDataForMethod( - new SingleTestGenerator.GeneratedClassData("ClassName", "com.example", - new File("target/test.java").toPath()), - "some_method" - ) - @Shared ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties( assertJsonSize: true, generatedTestSourcesDir: new File("."), generatedTestResourcesDir: new File(".") ) + @Shared + GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod( + new SingleTestGenerator.GeneratedClassData("foo", "bar", new File(".").toPath()), "method") + + @Shared + SingleTestGenerator.GeneratedClassData generatedClassData = + new SingleTestGenerator.GeneratedClassData("foo", "com.example", new File(".").toPath()) + + def setup() { + properties = new ContractVerifierConfigProperties( + assertJsonSize: true + ) + } + + private String singleTestGenerator(Contract contractDsl) { + return new JavaTestGenerator() { + @Override + ClassBodyBuilder classBodyBuilder(BlockBuilder builder, GeneratedClassMetaData metaData, SingleMethodBuilder methodBuilder) { + return super.classBodyBuilder(builder, metaData, methodBuilder).field(new Field() { + @Override + boolean accept() { + return metaData.configProperties.testMode == TestMode.JAXRSCLIENT + } + + @Override + Field call() { + builder.addLine("WebTarget webTarget") + return this + } + }) + } + }.buildClass(properties, [contractMetadata(contractDsl)], "foo", generatedClassData) + } + + private ContractMetadata contractMetadata(Contract contractDsl) { + return new ContractMetadata(new File(".").toPath(), false, 0, null, contractDsl) + } + @Unroll def 'should generate correct verification from xml with body matchers [#methodBuilderName]'() { given: @@ -85,7 +119,7 @@ class XmlMethodBodyBuilderSpec extends Specification { """ bodyMatchers { xPath('/test/duck/text()', byRegex("[0-9]{3}")) - xPath('/test/duck/text()', byCommand('test($it)')) + xPath('/test/duck/text()', byCommand('equals($it)')) xPath('/test/duck/xxx', byNull()) xPath('/test/duck/text()', byEquality()) xPath('/test/alpha/text()', byRegex(onlyAlphaUnicode())) @@ -100,11 +134,9 @@ class XmlMethodBodyBuilderSpec extends Specification { } } // end::xmlgroovy[] - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(' ') + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThat(valueFromXPath(parsedXml, "/test/list/elem/text()")).isEqualTo("abc")') test.contains('assertThat(valueFromXPath(parsedXml, "/test/list/elem[2]/text()")).isEqualTo("def")') @@ -112,7 +144,7 @@ class XmlMethodBodyBuilderSpec extends Specification { test.contains('assertThat(valueFromXPath(parsedXml, "/test/aBoolean/text()")).isEqualTo("true")') test.contains('assertThat(valueFromXPath(parsedXml, "/test/valueWithoutAMatcher/text()")).isEqualTo("foo")') test.contains('assertThat(valueFromXPath(parsedXml, "/test/duck/text()")).matches("[0-9]{3}")') - test.contains('test("123")') + test.contains('equals("123")') test.contains('assertThat(nodeFromXPath(parsedXml, "/test/duck/xxx")).isNull()') test.contains('assertThat(valueFromXPath(parsedXml, "/test/duck/text()")).isEqualTo("123")') test.contains('assertThat(valueFromXPath(parsedXml, "/test/alpha/text()")).matches("[\\\\p{L}]*")') @@ -124,15 +156,24 @@ class XmlMethodBodyBuilderSpec extends Specification { test.contains('assertThat(valueFromXPath(parsedXml, "/test/*/complex/text()")).isEqualTo("foo")') test.contains('assertThat(valueFromXPath(parsedXml, "/test/duck/@type")).isEqualTo("xtype")') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder. - toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, classDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, classDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "junit" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } } def 'should throw exception for verification by type'() { @@ -159,11 +200,9 @@ class XmlMethodBodyBuilderSpec extends Specification { } } } - MethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl, properties, classDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(' ') + properties.testMode = TestMode.MOCKMVC when: - builder.appendTo(blockBuilder) - blockBuilder.toString() + singleTestGenerator(contractDsl) then: thrown UnsupportedOperationException } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/YamlMockMvcMethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/YamlMockMvcMethodBodyBuilderSpec.groovy index 0e3e66ccfb..37837b99f7 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/YamlMockMvcMethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/YamlMockMvcMethodBodyBuilderSpec.groovy @@ -16,7 +16,7 @@ package org.springframework.cloud.contract.verifier.builder -import org.codehaus.groovy.control.MultipleCompilationErrorsException + import org.junit.Rule import spock.lang.Issue import spock.lang.Shared @@ -26,8 +26,11 @@ import spock.util.environment.RestoreSystemProperties import org.springframework.boot.test.rule.OutputCapture 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.converter.YamlContractConverter import org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockStubVerifier +import org.springframework.cloud.contract.verifier.file.ContractMetadata import org.springframework.cloud.contract.verifier.util.SyntaxChecker /** @@ -48,6 +51,40 @@ class YamlMockMvcMethodBodyBuilderSpec extends Specification implements WireMock GeneratedClassDataForMethod generatedClassDataForMethod = new GeneratedClassDataForMethod( new SingleTestGenerator.GeneratedClassData("foo", "bar", new File(".").toPath()), "method") + @Shared + SingleTestGenerator.GeneratedClassData generatedClassData = + new SingleTestGenerator.GeneratedClassData("foo", "com.example", new File(".").toPath()) + + def setup() { + properties = new ContractVerifierConfigProperties( + assertJsonSize: true + ) + } + + private String singleTestGenerator(Contract contractDsl) { + return new JavaTestGenerator() { + @Override + ClassBodyBuilder classBodyBuilder(BlockBuilder builder, GeneratedClassMetaData metaData, SingleMethodBuilder methodBuilder) { + return super.classBodyBuilder(builder, metaData, methodBuilder).field(new Field() { + @Override + boolean accept() { + return metaData.configProperties.testMode == TestMode.JAXRSCLIENT + } + + @Override + Field call() { + builder.addLine("WebTarget webTarget") + return this + } + }) + } + }.buildClass(properties, [contractMetadata(contractDsl)], "foo", generatedClassData) + } + + private ContractMetadata contractMetadata(Contract contractDsl) { + return new ContractMetadata(new File(".").toPath(), false, 0, null, contractDsl) + } + static File textToFile(String text) { File temp = File.createTempFile("yaml", ".yml") temp.text = text @@ -58,126 +95,6 @@ class YamlMockMvcMethodBodyBuilderSpec extends Specification implements WireMock return new YamlContractConverter().convertFrom(textToFile(text))[0] } - @Shared - String contractDslWithCookiesValue = """\ ---- -request: - method: "GET" - url: "/foo" - headers: - 'Accept': 'application/json' - cookies: - 'cookie-key': 'cookie-value' -response: - status: 200 - headers: - 'Content-Type': 'application/json' - cookies: - 'cookie-key': 'new-cookie-value' - body: - status: 'OK' -""" - - @Shared - String contractDslWithCookiesPattern = """\ ---- -request: - method: "GET" - url: "/foo" - headers: - 'Accept': 'application/json' - cookies: - 'cookie-key': 'cookie-value' - matchers: - cookies: - - key: 'cookie-key' - regex: '[A-Za-z]+' -response: - status: 200 - headers: - 'Content-Type': 'application/json' - cookies: - 'cookie-key': 'new-cookie-value' - body: - status: 'OK' - matchers: - cookies: - - key: 'cookie-key' - regex: '[A-Za-z]+' -""" - - // TODO: Add absent - @Shared - String contractDslWithAbsentCookies = """\ ---- -request: - method: "GET" - url: "/foo" - headers: - 'Accept': 'application/json' - cookies: - 'cookie-key': 'cookie-value' - matchers: - cookies: - - key: 'cookie-key' - regex: '[A-Za-z]+' -response: - status: 200 - headers: - 'Content-Type': 'application/json' - cookies: - 'cookie-key': 'new-cookie-value' - body: - status: 'OK' - matchers: - cookies: - - key: 'cookie-key' - absent -""" - - @Shared - // tag::contract_with_regex[] - String dslWithOptionalsInString = """\ ---- -priority: 1 -request: - method: "POST" - url: "/users/password" - headers: - 'Content-Type': 'application/json' - body: - email: 'abc@abc.com' - callback_url: 'http://partners.com' - matchers: - headers: - - key: 'Content-Type' - regex: 'application/json.*' - body: - - path: \$.email - predefined: email - - path: \$.callback_url - predefined: hostname -response: - status: 404 - headers: - 'Content-Type': 'application/json' - body: - code: "123123" - message: "User not found by email = [not.existing@user.com]" - matchers: - headers: - - key: 'Content-Type' - regex: 'application/json.*' - body: - - path: \$.code - type: by_regex - value: "[123123]?" - - path: \$.message - type: by_regex - value: "User not found by email = [[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,6}]" -""" - // end::contract_with_regex[] - def 'should generate assertions for simple response body with #methodBuilderName'() { given: String contract = """\ @@ -192,21 +109,20 @@ response: "property2": "b" """ Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } } @Issue("#187") @@ -225,22 +141,21 @@ response: "property3": false """ Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("true")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").isNull()""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property3']").isEqualTo(false)""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("true")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").isNull()""") + test.contains("""assertThatJson(parsedJson).field("['property3']").isEqualTo(false)""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } } @Issue('#79') @@ -260,24 +175,22 @@ response: - "b" : "sthElse" """ Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#79') @@ -299,24 +212,23 @@ response: - "b" : "sthElse" """ Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").hasSize(2)""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['a']").isEqualTo("sth")""") + test.contains("""assertThatJson(parsedJson).array("['property2']").hasSize(2)""") + test.contains("""assertThatJson(parsedJson).array("['property2']").contains("['b']").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#82') @@ -334,21 +246,24 @@ response: status: 200 """ Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains(bodyString) + test.contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | """.body('''{\"items\":[\"HOP\"]}''')""" - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("{\\"items\\":[\\"HOP\\"]}")' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("{\\"items\\":[\\"HOP\\"]}")' + methodBuilderName | methodBuilder | bodyString + "spock" | { properties.testFramework = TestFramework.SPOCK } | """.body('''{\"items\":[\"HOP\"]}''')""" + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | '.body("{\\"items\\":[\\"HOP\\"]}")' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | '.body("{\\"items\\":[\\"HOP\\"]}")' } @Issue('#88') @@ -364,21 +279,20 @@ response: status: 200 """ Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains(bodyString) + test.contains(bodyString) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) and: stubMappingIsValidWireMockStub(contractDsl) where: - methodBuilderName | methodBuilder | bodyString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | """.body('''property1=VAL1''')""" - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("property1=VAL1")' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("property1=VAL1")' + methodBuilderName | methodBuilder | bodyString + "spock" | { properties.testFramework = TestFramework.SPOCK } | """.body('''property1=VAL1''')""" + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '.body("property1=VAL1")' + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } | '.body("property1=VAL1")' } @Issue('185') @@ -398,22 +312,21 @@ response: 7: 0.0 """ Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property']").field("['7']").isEqualTo(0.0)""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property']").field("['14']").isEqualTo(0.0)""") + test.contains("""assertThatJson(parsedJson).field("['property']").field("['7']").isEqualTo(0.0)""") + test.contains("""assertThatJson(parsedJson).field("['property']").field("['14']").isEqualTo(0.0)""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate assertions for array in response body with #methodBuilderName'() { @@ -436,22 +349,21 @@ response: ]' """ Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("['property2']").isEqualTo("b")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).array().contains("['property2']").isEqualTo("b")""") + test.contains("""assertThatJson(parsedJson).array().contains("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate assertions for array inside response body element with #methodBuilderName'() { @@ -473,22 +385,21 @@ response: }' """ Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property1']").contains("['property2']").isEqualTo("test1")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).array("['property1']").contains("['property3']").isEqualTo("test2")""") + test.contains("""assertThatJson(parsedJson).array("['property1']").contains("['property2']").isEqualTo("test1")""") + test.contains("""assertThatJson(parsedJson).array("['property1']").contains("['property3']").isEqualTo("test2")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate assertions for nested objects in response body with #methodBuilderName'() { @@ -507,22 +418,21 @@ response: }' """ Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property2']").field("['property3']").isEqualTo("b")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""assertThatJson(parsedJson).field("['property2']").field("['property3']").isEqualTo("b")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate regex assertions for map objects in response body with #methodBuilderName'() { @@ -545,22 +455,21 @@ response: regexType: as_integer ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) + String test = singleTestGenerator(contractDsl) then: - blockBuilder.toString().contains("""\$.property2", String.class)).matches("[0-9]{3}")""") - blockBuilder.toString().contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") + test.contains("""\$.property2", String.class)).matches("[0-9]{3}")""") + test.contains("""assertThatJson(parsedJson).field("['property1']").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def "should generate a call with an url path and query parameters with #methodBuilderName"() { @@ -608,11 +517,9 @@ response: property2: "b" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''.queryParam("limit","10")''') test.contains('''.queryParam("offset","20")''') @@ -628,12 +535,12 @@ response: and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#169') @@ -684,11 +591,9 @@ response: property2: "b" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''.queryParam("limit","10")''') test.contains('''.queryParam("offset","20")''') @@ -704,12 +609,12 @@ response: and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } def 'should generate test for empty body with #methodBuilderName'() { @@ -724,22 +629,20 @@ response: status: 406 ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ".body('''''')" - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("")' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.body("")' + methodBuilderName | methodBuilder | bodyString + "spock" | { properties.testFramework = TestFramework.SPOCK } | ".body('''''')" + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '.body("")' + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } | '.body("")' } def 'should generate test for String in response body with #methodBuilderName'() { @@ -755,23 +658,27 @@ response: body: "test" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(bodyDefinitionString) test.contains(bodyEvaluationString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'def responseBody = (response.body.asString())' | 'responseBody == "test"' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'String responseBody = response.getBody().asString();' | 'assertThat(responseBody).isEqualTo("test");' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'String responseBody = response.getBody().asString();' | 'assertThat(responseBody).isEqualTo("test");' + methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | 'String responseBody = response.body.asString()' | "responseBody == 'test'" + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | 'String responseBody = response.getBody().asString();' | 'assertThat(responseBody).isEqualTo("test");' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | 'String responseBody = response.getBody().asString();' | 'assertThat(responseBody).isEqualTo("test");' } @Issue('113') @@ -807,22 +714,24 @@ response: regex: 'http://localhost/partners/[0-9]+/users/[0-9]+' ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(headerEvaluationString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | headerEvaluationString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''response.header('Location') ==~ java.util.regex.Pattern.compile('http://localhost/partners/[0-9]+/users/[0-9]+')''' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'assertThat(response.header("Location")).matches("http://localhost/partners/[0-9]+/users/[0-9]+");' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | 'assertThat(response.header("Location")).matches("http://localhost/partners/[0-9]+/users/[0-9]+");' + methodBuilderName | methodBuilder | headerEvaluationString + "spock" | { properties.testFramework = TestFramework.SPOCK } | '''response.header("Location") ==~ java.util.regex.Pattern.compile('http://localhost/partners/[0-9]+/users/[0-9]+')''' + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | 'assertThat(response.header("Location")).matches("http://localhost/partners/[0-9]+/users/[0-9]+");' + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | 'assertThat(response.header("Location")).matches("http://localhost/partners/[0-9]+/users/[0-9]+");' } def 'should work with more complex stuff and jsonpaths with #methodBuilderName'() { @@ -854,23 +763,21 @@ response: message: "incorrect_format" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains("""assertThatJson(parsedJson).array("['errors']").contains("['property']").isEqualTo("bank_account_number")""") test.contains("""assertThatJson(parsedJson).array("['errors']").contains("['message']").isEqualTo("incorrect_format")""") and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('72') @@ -898,20 +805,24 @@ response: command: assertThatLocationIsNull($it) ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: assertionStrings.each { String assertionString -> assert test.contains(assertionString) } where: - methodBuilderName | methodBuilder | assertionStrings - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['''assertThatRejectionReasonIsNull(parsedJson.read("\\\$.rejectionReason"))''', '''assertThatLocationIsNull(response.header('Location'))'''] - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] + methodBuilderName | methodBuilder | assertionStrings + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | ['''assertThatRejectionReasonIsNull(parsedJson.read("\\\$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] } def "shouldn't generate unicode escape characters with #methodBuilderName"() { @@ -949,20 +860,18 @@ response: regex: 'application/json.*' ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains("\\u041f") and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('180') @@ -1010,31 +919,35 @@ response: regex: 'application/json.*' ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: for (String requestString : requestStrings) { assert test.contains(requestString) } and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | requestStrings - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - """.param('formParameter', '"formParameterValue"'""", - """.param('someBooleanParameter', 'true')""", - """.multiPart('file', 'filename.csv', 'file content'.bytes, 'application/json')"""] - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.param("formParameter", "\\"formParameterValue\\"")', - '.param("someBooleanParameter", "true")', - '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.param("formParameter", "\\"formParameterValue\\"")', - '.param("someBooleanParameter", "true")', - '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] + methodBuilderName | methodBuilder | requestStrings + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + """.param('formParameter', '''"formParameterValue"'''""", + """.param('someBooleanParameter', 'true')""", + """.multiPart('file', 'filename.csv', 'file content'.bytes, 'application/json')"""] + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.param("formParameter", "\\"formParameterValue\\"")', + '.param("someBooleanParameter", "true")', + '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.param("formParameter", "\\"formParameterValue\\"")', + '.param("someBooleanParameter", "true")', + '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] } @@ -1083,25 +996,29 @@ response: regex: 'application/json.*' ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: for (String requestString : requestStrings) { assert test.contains(requestString) } and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | requestStrings - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - """.multiPart('file', 'filename.csv', 'file content'.bytes, 'application/json')"""] - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] + methodBuilderName | methodBuilder | requestStrings + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + """.multiPart('file', 'filename.csv', 'file content'.bytes, 'application/json')"""] + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.multiPart("file", "filename.csv", "file content".getBytes(), "application/json");'] } @@ -1152,31 +1069,35 @@ response: regex: 'application/json.*' ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: for (String requestString : requestStrings) { assert test.contains(requestString) } and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | requestStrings - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - """.param('formParameter', '"formParameterValue"'""", - """.param('someBooleanParameter', 'true')""", - """.multiPart('file', toString(), 'file content'.bytes, 'application/json')"""] - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.param("formParameter", "\\"formParameterValue\\"")', - '.param("someBooleanParameter", "true")', - '.multiPart("file", toString(), "file content".getBytes(), "application/json");'] - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', - '.param("formParameter", "\\"formParameterValue\\"")', - '.param("someBooleanParameter", "true")', - '.multiPart("file", toString(), "file content".getBytes(), "application/json");'] + methodBuilderName | methodBuilder | requestStrings + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + """.param('formParameter', '''"formParameterValue"'''""", + """.param('someBooleanParameter', 'true')""", + """.multiPart('file', toString(), 'file content'.bytes, 'application/json')"""] + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.param("formParameter", "\\"formParameterValue\\"")', + '.param("someBooleanParameter", "true")', + '.multiPart("file", toString(), "file content".getBytes(), "application/json");'] + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | ['"Content-Type", "multipart/form-data;boundary=AaB03x"', + '.param("formParameter", "\\"formParameterValue\\"")', + '.param("someBooleanParameter", "true")', + '.multiPart("file", toString(), "file content".getBytes(), "application/json");'] } @@ -1201,15 +1122,13 @@ response: regexType: as_string ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''assertThat(parsedJson.read("\\$.authorities[0]", String.class)).matches("^[a-zA-Z0-9_\\\\- ]+\\$")''') and: - SyntaxChecker.tryToCompileWithoutCompileStatic("spock", blockBuilder.toString()) + SyntaxChecker.tryToCompileWithoutCompileStatic("spock", test) } @Issue('#216') @@ -1232,15 +1151,13 @@ response: value: '^[a-zA-Z0-9_\\- ]+$' ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''assertThat(parsedJson.read("$.authorities[0]", String.class)).matches("^[a-zA-Z0-9_\\\\- ]+$")''') and: - SyntaxChecker.tryToCompileJava(MockMvcJUnitMethodBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileJava("mockmvc", test) } def 'should work with execution property with #methodBuilderName'() { @@ -1262,18 +1179,16 @@ response: value: "assertThatRejectionReasonIsNull($it)" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('''assertThatJson(parsedJson).field("[\'rejectionReason']").isEqualTo("assertThatRejectionReasonIsNull("''') test.contains('''assertThatRejectionReasonIsNull(''') where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } } @Issue('262') @@ -1301,16 +1216,14 @@ response: value: "[0-9]+" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThat(parsedJson.read("\\$[0].id", String.class)).matches("[0-9]+")') test.contains('assertThat(parsedJson.read("\\$[1].id", String.class)).matches("[0-9]+")') and: - SyntaxChecker.tryToCompileWithoutCompileStatic("spock", blockBuilder.toString()) + SyntaxChecker.tryToCompileWithoutCompileStatic("spock", test) } @Issue('266') @@ -1333,11 +1246,9 @@ response: "Content-Type": "application/json;charset=UTF-8" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).arrayField().contains("Java8").value()') test.contains('assertThatJson(parsedJson).arrayField().contains("Spring").value()') @@ -1345,12 +1256,12 @@ response: test.contains('assertThatJson(parsedJson).arrayField().contains("Stream").value()') test.contains('assertThatJson(parsedJson).arrayField().contains("SpringBoot").value()') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('266') @@ -1370,11 +1281,10 @@ response: ''' Contract contractDsl = fromYaml(contract) System.setProperty('spring.cloud.contract.verifier.assert.size', 'true') - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).hasSize(5)') test.contains('assertThatJson(parsedJson).arrayField().contains("Java8").value()') @@ -1383,12 +1293,12 @@ response: test.contains('assertThatJson(parsedJson).arrayField().contains("Stream").value()') test.contains('assertThatJson(parsedJson).arrayField().contains("SpringBoot").value()') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('266') @@ -1406,23 +1316,21 @@ response: "Content-Type": "application/json;charset=UTF-8" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).array().array().arrayField().isEqualTo("Programming").value()') test.contains('assertThatJson(parsedJson).array().array().arrayField().isEqualTo("Java").value()') test.contains('assertThatJson(parsedJson).array().array().arrayField().isEqualTo("Spring").value()') test.contains('assertThatJson(parsedJson).array().array().arrayField().isEqualTo("Boot").value()') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('47') @@ -1438,21 +1346,19 @@ response: status: 200 ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains(bodyDefinitionString) and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | bodyDefinitionString - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.when().async()' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '.when().async()' + methodBuilderName | methodBuilder | bodyDefinitionString + "spock" | { properties.testFramework = TestFramework.SPOCK } | '.when().async()' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '.when().async()' } @Issue('372') @@ -1470,22 +1376,20 @@ response: status: 200 ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() - def strippedTest = test.replace('\n', '').replace(' ', '').stripIndent().stripMargin() + String test = singleTestGenerator(contractDsl) + def strippedTest = test.replace('\n', '').replace(' ', '').replaceAll("\t", "").stripIndent().stripMargin() then: strippedTest.contains('.queryParam("param","value").when().async().get("/test")') and: stubMappingIsValidWireMockStub(contractDsl) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } } def 'should generate proper test code with array of primitives using #methodBuilderName'() { @@ -1504,21 +1408,19 @@ response: - CASH ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatJson(parsedJson).array().field("[\'partners\']").array("[\'payment_methods\']").arrayField().isEqualTo("BANK").value()') test.contains('assertThatJson(parsedJson).array().field("[\'partners\']").array("[\'payment_methods\']").arrayField().isEqualTo("CASH").value()') and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#273') @@ -1541,15 +1443,13 @@ response: value: '^(?!\\s*$).+' ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThat(parsedJson.read("\\$.message", String.class)).matches("^(?!\\\\s*\\$).+")') and: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString(), + SyntaxChecker.tryToCompileGroovy("spock", test, false) } @@ -1574,18 +1474,12 @@ response: value: "assertThatRejectionReasonIsNull($it)" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.then(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('assertThatRejectionReasonIsNull(parsedJson.read("\\\$.rejectionReason.title"))') - when: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) - then: - def e = thrown(MultipleCompilationErrorsException) - e.message.contains('Cannot find matching method Script1#assertThatRejectionReasonIsNull') + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#85') @@ -1611,11 +1505,9 @@ response: value: "assertThatUserNameIsNotNull($it)" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.then(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''assertThatUserNameIsNotNull(parsedJson.read("\\$[0].name"))''') test.contains('''assertThatUserNameIsNotNull(parsedJson.read("\\$[1].name"))''') @@ -1644,11 +1536,9 @@ response: value: "assertThatUserNameIsNotNull($it)" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = new MockMvcJUnitMethodBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.JUNIT when: - builder.then(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$[0].name")''') test.contains('''assertThatUserNameIsNotNull(parsedJson.read("$[1].name")''') @@ -1672,18 +1562,12 @@ response: status: 200 ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.given(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('.header("authorization", getOAuthTokenHeader())') - when: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) - then: - def e = thrown(MultipleCompilationErrorsException) - e.message.contains('Cannot find matching method Script1#getOAuthTokenHeader') + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#150') @@ -1703,15 +1587,13 @@ response: value: ".*" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains("responseBody ==~ java.util.regex.Pattern.compile('.*')") and: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#150') @@ -1731,18 +1613,12 @@ response: value: "foo($it)" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = new HttpSpockMethodRequestProcessingBodyBuilder(contractDsl, properties, generatedClassDataForMethod) - BlockBuilder blockBuilder = new BlockBuilder(" ") + properties.testFramework = TestFramework.SPOCK when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('foo(responseBody)') - when: - SyntaxChecker.tryToCompileGroovy(HttpSpockMethodRequestProcessingBodyBuilder.simpleName, blockBuilder.toString()) - then: - def e = thrown(MultipleCompilationErrorsException) - e.message.contains('Cannot find matching method Script1#foo') + SyntaxChecker.tryToCompileGroovy("spock", test) } @Issue('#162') @@ -1769,24 +1645,28 @@ response: regex: 'application.vnd.fraud.v1.json.*' ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: matcher(test) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | matcher - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String s -> 'assertThat(response.header("Content-Type")).matches("application.vnd.fraud.v1.json.*")' } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String s -> "response.header('Content-Type') ==~ java.util.regex.Pattern.compile('application.vnd.fraud.v1.json.*')" } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String s -> "response.header('Content-Type') ==~ java.util.regex.Pattern.compile('application.vnd.fraud.v1.json.*')" } + methodBuilderName | methodBuilder | matcher + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | { String s -> 'assertThat(response.header("Content-Type")).matches("application.vnd.fraud.v1.json.*")' } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | { String s -> "response.header('Content-Type') ==~ java.util.regex.Pattern.compile('application.vnd.fraud.v1.json.*')" } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | { String s -> "response.header('Content-Type') ==~ java.util.regex.Pattern.compile('application.vnd.fraud.v1.json.*')" } } @Issue('#172') - def 'should resolve plain text properly via headers'() { + def 'should resolve plain text properly via headers with #methodBuilderName'() { given: String contract = '''\ --- @@ -1806,22 +1686,20 @@ response: regex: 'text/plain.*' ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: !test.contains('assertThatJson(parsedJson).field("[\'a\']").isEqualTo(1)') test.contains(expectedAssertion) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: //order is inverted cause Intellij didn't parse this properly - methodBuilderName | methodBuilder | expectedAssertion - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''responseBody == "{\\"a\\":1}\\n{\\"a\\":2}''' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' + methodBuilderName | methodBuilder | expectedAssertion + "spock" | { properties.testFramework = TestFramework.SPOCK } | """responseBody == '''{"a":1}\\n{"a":2}\\n'''""" + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}\\n''' + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}\\n''' } @Issue('#443') @@ -1846,21 +1724,27 @@ response: regex: 'application/json;charset=utf-8.*' ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: testAssertion(test) and: - SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompile(methodBuilderName, test) where: - methodBuilderName | methodBuilder | testAssertion - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String testContents -> testContents.contains("""responseBody ==~ java.util.regex.Pattern.compile('true|false')""") } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String testContents -> testContents.contains("""responseBody ==~ java.util.regex.Pattern.compile('true|false')""") } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } + methodBuilderName | methodBuilder | testAssertion + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | { String testContents -> testContents.contains("""responseBody ==~ java.util.regex.Pattern.compile('true|false')""") } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | { String testContents -> testContents.contains("""responseBody ==~ java.util.regex.Pattern.compile("true|false")""") } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | { String testContents -> testContents.contains("""assertThat(responseBody).matches("true|false");""") } } @Issue('#169') @@ -1887,20 +1771,18 @@ response: value: 'some value "with quote"|bar' ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + methodBuilder() when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + String test = singleTestGenerator(contractDsl) then: test.contains('.matches("some value \\"with quote\\"|bar")') and: - SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, blockBuilder.toString()) + SyntaxChecker.tryToCompileWithoutCompileStatic(methodBuilderName, test) where: //order is inverted cause Intellij didn't parse this properly - methodBuilderName | methodBuilder | expectedAssertion - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''responseBody == "{\\"a\\":1}\\n{\\"a\\":2}"''' - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' + methodBuilderName | methodBuilder | expectedAssertion + "spock" | { properties.testFramework = TestFramework.SPOCK } | '''responseBody == "{\\"a\\":1}\\n{\\"a\\":2}"''' + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' } @Issue('#169') @@ -1909,32 +1791,35 @@ response: Contract contractDsl = Contract.make { request { method 'POST' - url $(c("foo"), p(execute("executedMethod()"))) + url $(c("foo"), p(execute("toString()"))) } response { status OK() } } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: - SyntaxChecker.tryToCompile(methodBuilderName, test) + String test = singleTestGenerator(contractDsl) then: - def e = thrown(Throwable) - missingMethodAssertion(e, capture) + SyntaxChecker.tryToCompile(methodBuilderName, test) and: - test.contains("executedMethod()") - !test.contains("\"executedMethod()\"") - !test.contains("'executedMethod()'") + test.contains("toString()") + !test.contains("\"toString()\"") + !test.contains("'toString()'") where: - methodBuilderName | methodBuilder | missingMethodAssertion - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { Throwable t, OutputCapture capture -> t.message.contains("Cannot find matching method Script1#executedMethod") } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { Throwable t, OutputCapture capture -> t.message.contains("Truncated class file") && capture.toString().contains("post(executedMethod())") } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { Throwable t, OutputCapture capture -> t.message.contains("Cannot find matching method Script1#executedMethod") } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { Throwable t, OutputCapture capture -> t.message.contains("Truncated class file") && capture.toString().contains("path(executedMethod())") } + methodBuilderName | methodBuilder + "spock" | { + properties.testFramework = TestFramework.SPOCK + } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } } @Issue('#203') @@ -1955,23 +1840,24 @@ response: - "baz" ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: - SyntaxChecker.tryToCompile(methodBuilderName, test) + String test = singleTestGenerator(contractDsl) then: + SyntaxChecker.tryToCompile(methodBuilderName, test) test.contains('assertThatJson(parsedJson).array("[\'list\']").isEmpty()') !test.contains('assertThatJson(parsedJson).array("[\'foo\']").isEmpty()') where: - methodBuilderName | methodBuilder - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } + methodBuilderName | methodBuilder + "spock" | { properties.testFramework = TestFramework.SPOCK } + "mockmvc" | { properties.testMode = TestMode.MOCKMVC } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } + "webclient" | { properties.testMode = TestMode.WEBTESTCLIENT } } @Issue('#226') @@ -1988,22 +1874,29 @@ response: body: 12000 ''' Contract contractDsl = fromYaml(contract) - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") - and: - builder.appendTo(blockBuilder) - String test = blockBuilder.toString() + methodBuilder() when: - SyntaxChecker.tryToCompile(methodBuilderName, test) + String test = singleTestGenerator(contractDsl) then: + SyntaxChecker.tryToCompile(methodBuilderName, test) requestAssertion(test) responseAssertion(test) where: - methodBuilderName | methodBuilder | requestAssertion | responseAssertion - HttpSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new HttpSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains("body('''12000''')") } | { String body -> body.contains('responseBody == "12000"') } - MockMvcJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains('body("12000")') } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000");') } - JaxRsClientSpockMethodRequestProcessingBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains(""".method('GET', entity('12000', 'text/plain'))""") } | { String body -> body.contains('responseBody == "12000"') } - JaxRsClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains(""".method("GET", entity("12000", "text/plain"))""") } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000")') } - WebTestClientJUnitMethodBodyBuilder.simpleName | { Contract dsl -> new WebTestClientJUnitMethodBodyBuilder(dsl, properties, generatedClassDataForMethod) } | { String body -> body.contains('body("12000")') } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000");') } + methodBuilderName | methodBuilder | requestAssertion | responseAssertion + "spock" | { + properties.testFramework = TestFramework.SPOCK + } | { String body -> body.contains("body('''12000''')") } | { String body -> body.contains("responseBody == '12000'") } + "mockmvc" | { + properties.testMode = TestMode.MOCKMVC + } | { String body -> body.contains('body("12000")') } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000");') } + "jaxrs-spock" | { + properties.testFramework = TestFramework.SPOCK; properties.testMode = TestMode.JAXRSCLIENT + } | { String body -> body.contains(""".build("GET", entity("12000", "text/plain"))""") } | { String body -> body.contains('responseBody == "12000"') } + "jaxrs" | { + properties.testFramework = TestFramework.JUNIT; properties.testMode = TestMode.JAXRSCLIENT + } | { String body -> body.contains(""".build("GET", entity("12000", "text/plain"))""") } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000")') } + "webclient" | { + properties.testMode = TestMode.WEBTESTCLIENT + } | { String body -> body.contains('body("12000")') } | { String body -> body.contains('assertThat(responseBody).isEqualTo("12000");') } } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/SyntaxChecker.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/SyntaxChecker.groovy index f0ab52629b..f3f22ea8c8 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/SyntaxChecker.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/SyntaxChecker.groovy @@ -29,6 +29,7 @@ import com.jayway.jsonpath.DocumentContext import com.jayway.jsonpath.JsonPath import com.toomuchcoding.jsonassert.JsonAssertion import groovy.transform.CompileStatic +import groovy.util.logging.Commons import io.restassured.RestAssured import io.restassured.module.mockmvc.RestAssuredMockMvc import io.restassured.module.webtestclient.RestAssuredWebTestClient @@ -51,11 +52,11 @@ import org.springframework.cloud.contract.verifier.messaging.internal.ContractVe import org.springframework.cloud.contract.verifier.messaging.internal.ContractVerifierObjectMapper import org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil import org.springframework.util.ReflectionUtils - /** * checking the syntax of produced scripts */ @CompileStatic +@Commons class SyntaxChecker { Entity entity @@ -114,23 +115,33 @@ private void test(String test) { \t}''' static void tryToCompile(String builderName, String test) { - if (builderName.toLowerCase().contains("spock")) { - tryToCompileGroovy(builderName, test) - } - else { - tryToCompileJava(builderName, test) + try { + if (builderName.toLowerCase().contains("spock")) { + tryToCompileGroovy(builderName, test) + } + else { + tryToCompileJava(builderName, test) + } + } catch (Throwable t) { + log.error("Exception occurred while trying to compile the test [\n" + test + "\n]") + throw t } } static void tryToRun(String builderName, String test) { - if (builderName.toLowerCase().contains("spock")) { - Script script = tryToCompileGroovy(builderName, test) - script.run() - } - else { - Class clazz = tryToCompileJava(builderName, test) - Method method = ReflectionUtils.findMethod(clazz, "method") - method.invoke(clazz.newInstance()) + try { + if (builderName.toLowerCase().contains("spock")) { + Script script = tryToCompileGroovy(builderName, test) + script.invokeMethod("validate_method()", null) + } + else { + Class clazz = tryToCompileJava(builderName, test) + Method method = ReflectionUtils.findMethod(clazz, "validate_method") + method.invoke(clazz.newInstance()) + } + } catch (Throwable t) { + log.error("Exception occurred while trying to run the test [\n" + test + "\n]") + throw t } } @@ -144,7 +155,7 @@ private void test(String test) { } } - static Script tryToCompileGroovy(String builderName, String test, boolean compileStatic = true) { + static Script tryToCompileGroovy(String builderName, String test, boolean compileStatic = false) { def imports = new ImportCustomizer() CompilerConfiguration configuration = new CompilerConfiguration() if (compileStatic) { @@ -152,15 +163,14 @@ private void test(String test) { new ASTTransformationCustomizer(CompileStatic)) } configuration.addCompilationCustomizers(imports) - StringBuilder sourceCode = new StringBuilder() - sourceCode.append("${DEFAULT_IMPORTS_AS_STRING}\n") - sourceCode.append(getStaticImports(builderName)) - sourceCode.append("\n") - sourceCode.append("WebTarget webTarget") - sourceCode.append("\n") - sourceCode.append(test) - sourceCode.append(dummyMethod) - return new GroovyShell(SyntaxChecker.classLoader, configuration).parse(sourceCode.toString()) + String className = className(test) + test = updatedTest(test, className) + return new GroovyShell(SyntaxChecker.classLoader, configuration).parse(test) + } + + private static String updatedTest(String test, String className) { + test.replaceAll("class FooTest", "class " + className) + .replaceAll("import javax.ws.rs.core.Response", "import javax.ws.rs.core.Response; import javax.ws.rs.client.WebTarget;") } private static GString getStaticImports(String builderName) { @@ -171,26 +181,20 @@ private void test(String test) { } static Class tryToCompileJava(String builderName, String test) { + String className = className(test) + String fqnClassName = "com.example.${className}" + test = test.replaceAll("class FooTest", "class " + className) + .replaceAll("import javax.ws.rs.core.Response", "import javax.ws.rs.core.Response; import javax.ws.rs.client.WebTarget;") + return InMemoryJavaCompiler.compile(fqnClassName, test) + } + + private static String className(String test) { Random random = new Random() int first = Math.abs(random.nextInt()) int hashCode = Math.abs(test.hashCode()) StringBuffer sourceCode = new StringBuffer() String className = "TestClass_${first}_${hashCode}" - String fqnClassName = "com.example.${className}" - sourceCode.append("package com.example;\n") - sourceCode.append("${DEFAULT_IMPORTS_AS_STRING}\n") - sourceCode.append(getStaticImports(builderName)) - sourceCode.append("\n") - sourceCode.append("public class ${className} {\n") - sourceCode.append("\n") - sourceCode.append(" WebTarget webTarget;") - sourceCode.append("\n") - sourceCode.append(" public void method() throws Exception {\n") - sourceCode.append(" ${test}\n") - sourceCode.append(" }\n") - sourceCode.append(dummyMethod) - sourceCode.append("}") - return InMemoryJavaCompiler.compile(fqnClassName, sourceCode.toString()) + return className } static boolean tryToCompileJavaWithoutImports(String fqn, String test) { @@ -199,7 +203,12 @@ private void test(String test) { } static boolean tryToCompileGroovyWithoutImports(String test) { - new GroovyShell(SyntaxChecker.classLoader).parse(test) + try { + new GroovyShell(SyntaxChecker.classLoader).parse(test) + } catch (Throwable t) { + log.error("Exception occurred while trying to parse [\n${test}\n]", t) + throw t + } return true } diff --git a/spring-cloud-contract-verifier/src/test/resources/application.properties b/spring-cloud-contract-verifier/src/test/resources/application.properties new file mode 100644 index 0000000000..24edc25897 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/application.properties @@ -0,0 +1 @@ +logging.level.wiremock.com.github.jknack.handlebars.internal=INFO diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/name-with-hyphen/car-rental/diff.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/name-with-hyphen/car-rental/diff.groovy index 2098f4f5c9..27563de935 100644 --- a/spring-cloud-contract-verifier/src/test/resources/directory/with/name-with-hyphen/car-rental/diff.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/name-with-hyphen/car-rental/diff.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo7") + } + response { + status(207) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/01_login.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/01_login.groovy index 2098f4f5c9..fb050d1d99 100644 --- a/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/01_login.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/01_login.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo20") + } + response { + status(200) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/02_showCart.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/02_showCart.groovy index 2098f4f5c9..0c9dd6b699 100644 --- a/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/02_showCart.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/02_showCart.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo21") + } + response { + status(200) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/03_logout.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/03_logout.groovy index 2098f4f5c9..e0cd3a5fa7 100644 --- a/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/03_logout.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/scenario/03_logout.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo22") + } + response { + status(200) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/different/diff.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/different/diff.groovy index 2098f4f5c9..f0fa9a2c52 100644 --- a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/different/diff.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/different/diff.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo0") + } + response { + status(200) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/different/diff.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/different/diff.groovy index 2098f4f5c9..568f5efae0 100644 --- a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/different/diff.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/different/diff.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo3") + } + response { + status(203) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/other.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/other.groovy index 2098f4f5c9..bd5b4c3f5b 100644 --- a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/other.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/other.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo2") + } + response { + status(202) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/sample.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/sample.groovy index 2098f4f5c9..5fb5ea2279 100644 --- a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/sample.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/other/sample.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo1") + } + response { + status(201) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/exceptions/test.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/exceptions/test.groovy index 2098f4f5c9..0a30782d61 100644 --- a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/exceptions/test.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/exceptions/test.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo4") + } + response { + status(204) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/v1/exceptions/testv1.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/v1/exceptions/testv1.groovy index 2098f4f5c9..11fda5423f 100644 --- a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/v1/exceptions/testv1.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/v1/exceptions/testv1.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo5") + } + response { + status(205) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/v2/exceptions/testv2.groovy b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/v2/exceptions/testv2.groovy index 2098f4f5c9..146b18ff65 100644 --- a/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/v2/exceptions/testv2.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/directory/with/stubs/package/v2/exceptions/testv2.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo6") + } + response { + status(206) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/logback.xml b/spring-cloud-contract-verifier/src/test/resources/logback.xml new file mode 100644 index 0000000000..1690956653 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/resources/logback.xml @@ -0,0 +1,15 @@ + + + + %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n + + + + + + + + + + + \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/02_login.groovy b/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/02_login.groovy index 2098f4f5c9..7a088afbcc 100644 --- a/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/02_login.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/02_login.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo10") + } + response { + status(200) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/bar/03_login.groovy b/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/bar/03_login.groovy index b02d8d5f0d..47269107b5 100644 --- a/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/bar/03_login.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/bar/03_login.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,6 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - - +Contract.make { + request { + method(GET()) + url("/foo13") + } + response { + status(200) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/foo/01_login.groovy b/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/foo/01_login.groovy index 2098f4f5c9..ccf82aaea3 100644 --- a/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/foo/01_login.groovy +++ b/spring-cloud-contract-verifier/src/test/resources/strange_[3.3.3]_directory/foo/01_login.groovy @@ -1,3 +1,5 @@ +import org.springframework.cloud.contract.spec.Contract + /* * Copyright 2013-2019 the original author or authors. * @@ -13,5 +15,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - - +Contract.make { + request { + method(GET()) + url("/foo11") + } + response { + status(200) + } +} \ No newline at end of file diff --git a/spring-cloud-contract-verifier/worksWithPdf_request_request.pdf b/spring-cloud-contract-verifier/worksWithPdf_request_request.pdf new file mode 100644 index 0000000000000000000000000000000000000000..69503635d87cbdfa660d5cd8be66d3e74b3b20e8 GIT binary patch literal 14631 zcmch;Wn3KHw(c83@Bksf9THp`ZQR}6-Ra=&5Fog_yEhWtEx5Zw1Hs*0FYmkd-e;}7 z&i>u=;hx)FHmYXLn&Us7t}i_wGI?Q9I!1a{M6!d}n3(Y`B4%U(GQS;&6KfFz+1ZF0nSjJP!~i*BATdDX?IJVl+kxy~O_l$SSc!Rg z5lyU(|LTtT|L+eX^FJk`>}G313{Y1zF?~zJ#M;c!oS21!7$6F=bTqMl+glnqnh2X1 z*%-gI`o~`0z~0J%_%8@THkM9S)(*rh!~l7F6JwB(qmBJr>TkIb1JvF~FcLGpt#2G8 ztc^`v-%h-RtpA8jZHO5e--e+`3{bSOaeV9I?_;GmqQs1BfA{D7AKd;s9)N@}u@<)h z6T1nc0W*^+6EhP#yD1Z^5sR_0u>m^^8_*bN$jZq3|K399uOc`&+M5_yA-bj;85*yf z=^N^^BYaCv^ivn*_p3tb(L^=$HAZ&!S9ks>9bPoc|M_G10{pv+aTtcbs`nrF{$Hsh z;$KAmQ*H7FW+o1Qk^LLeKT0NK;AmiJWA;x%V*RH({qh$eo4g|v<9%K4-c`ZCQ2u-Rz<+wWkd3vY ziM68xG21^zEb}G~13{a=B*5_YW#s@8v$HV&rGz&zy*2!=)D%q|Y@Fr3?Q5r3Z+eLMXR^}NaMFXbsY+B+FJ{-a}uxAuU4@cN74 zKf(HIWdDixe+%nBFflPO{B_rV$s{9s9I=bxW8bM)XnKH?#5@aKaFFk^2G!lW7ia+i zFCT`(iG7JG-&pUC9VyNCGsWT!dw2_(qq83oi?aP{LISX@J!(>Zi=<%mt;aSh-nva0 z`jO1>gbyB@9}xa=1!Tr@e`+$Vm?pz_j|{o7tSRC8Z~?TP!XP2~C<71~ zFw5h`h$-Ys{@Uyeb#Dw$cUU9Ru_0neG8k&he@Z@q@rkbLLHr2?SFMxj6-eS{GZ{qr z#7hN~i%aN(#@*N4`8V;h|DWM_`$cmwv%fL@4?2uYjBl^Kf97-Sh2W_yGIv_iJPXkv z`5^cnVNgbp^piO8QCKwpd(vt+=}+HeiX?EWV@^KVp?AUiL9Lj4VB=T*kYtJmO}}12 znH|~aOG}>@nU|f%9vkib3ijZ_3m>~}JAL*(Z6gA`-ll^&Rd#1el!^|V--VzlFsQ_d zwh@rsTy*Jd+I$VYOD=vcj|?F6vbujn3JDZO)9@Il1JIT3D0IJU6Mb&C{KiA3CI}rf^N*j} ze4h4q0P~~PTt`Vi_TI(vrL{Mf1?7)xw{MO*$YlXO;(fNo2=$FNlYA$)d=`knLLENF z1DRm64Axk?GukJ&poN@a3!qegDq@h#ixDRM;Lf_CT7yKi0uOi%uE4Mkeb=|tET3S) zxm}IH;%`%c_pO#bo+L9Hall%HD!E;_PRtibNVylJDClnB|`#fGD;iK4lh6R?0A8!y18;kz`?0l3$zoe z-%f5T+LQFvq1A|`s~YWD@Pfsqy{d!A6@TmD{pzOcZWa#ri_0acoMVAu>)Vd%Jf z0ctcgH2;n{jdoI*_c2t@j`)q*=o25}agNfzFNz$R;9&n+zsbP5orXO&!~I!*SZ=`> z_5Q8})i!bJj;}b0H6)R^y_(@gaa|z%J|Z;e{gCgA@gbQxIy~BJDV#RI`zy5j|ln-|s*R{V?;jo{*U+EpZhY8CXz0 z_g$!Lg(B(#V$}5E6Dl8qj#46a)D`7guMtvhNOdErZo|Sg7OEk9^(#tDrccVfx1Kn+ zM`9duI7$)d9&(;yM)}C!QAz8clux)8Xm7hUc_UQ)D#Y;Dz8R@5?G{Y|nC9Z;Dk-En z%NDggN_pOc(a2J(yyLPSye7rN%$fT}8pZ@<7x~rTQFU@40uDVmLsQL4-~zS-2BHD? zdlwcmeZK2nO<7?#9UAvvKab(l%od~Eto`|-CZNyu-`oA92>v=^xVZB;CwN3R3~X0F z$C{Yae~bW1kfk;}s~x^_trKb1lbBgwK11w#cDp@K;yt=<2o90=yh9%d_*o~u5(hx= z7_w%U3Kfzu%<$yNnaqR9{9!|%)wAHY+>T&okNzV@rFIL36+;SON^pRtzI+n!$wP)*+svnleMDCP0ZIP6YqEq*&Xqe zUE|F2;fBJ|hxxPeV55{E)TxgSdKAfxpMl=iCth0yWw*1uSx&X5jED4Vm~<-*y{RZK zMx7fTA1~W0&ZS4MS(A4`F0UHjXOt>m@$0S%J~L-osow8UG;3w#O(%Hy&J}?|3Q!Is z@r#cj`X>T+U!2FW?$7SsH6z>{r&RU%atV{EymIIKC?zwIE~IBpe6zMSY6GpOA~)KJ zA8!hr4_dJW)VgmPlnKU^B}_85zb_d-M^5#!Y%M)26VFSI2`zn{=gp24geHxqh?FNf zXE!FLgty0wM`hY$#K5XP^;`*CM@sXz3|>Ttj@h(Q_F|%3x#~CFMw%sZLBr9T!or@$ z6;PV-+Td~@V2Y^dBU~~sEsU50EjXan!WeP;c~9rl?agas%->G1F6hz3q^XkbMu)!Q zv~ybF?KluzaAvD?i!D39g!K5eS@MX~EVtsFr%Xqr%(bfqAI2 z0p&T9l?&sW!LC5_(H7~l1F#JNn0rS230P_BR{XO8IPtv}299~)Q>oL-a!rN})yy1^ z9!2|*{rHOO9NAog>(8eKzg|RdK~|u8cK+KCO-;JtTpp+C*5p_E6*`k=gVb+__m7lo zQp`OJS9%f!hQOw}kTwjg_UX-bVmW@5zY@*t-)U3Gwrpn;+QsgySV&Mv7?PA z0tY>jt)PKta-eu%CT10#IK%C<`3;6`M+n6}qDTXDoL%3o8QZ&(Ts|HoT9~yjS0d}6 zyzmw+A5KKt{sn;VN&G3yXU}iQ(dbU7?{DARJT9jS9W<+ZIjHBBnB3!l6ZQEX$E0c# zgR7gtLmux|)L;&D<(aY!961YOoJwd5pXV)_ThT z+2q11(LJ8|&OFrAuZfbS=fh3Cq`5=rN2VSUeb}*3p&2|!YV*P@U|&NDK(pt``0Fa( zFjJD}tYjfbj^#L_`=YGrF8P%Y%47H48SL4^D@ccFcmN-b{IZ8}MM!j=(Cx!*oW&k_ z?&Sd4HK;RhK!_uoCA}jh=xcL%C-)iOdp5tXd9>Gt&BWw>$^(9YkrhDDmZuNtgu38Tzh|XH z&h52CXo-Lf0+|3@eV*J=9lzH$vOv<)wfuAnT4l55rF9WYBxt1Mp(%#-jZ#k{+{A>K zT)hq(U(U--qP8)H*Xa1Pgvuu8*bhG)q91x%ggE&+Rb87Nw#|*s^_R|in6Xx_EAh=g&f^X*@4}`7^9&CA}0Mki(Y1jQ%6dQEs$D3Sz6g?FEMSZ(HdU!r^ zPl+Eg^<~V{K4pH2ncyIy&+!nH?7~2}`CvvW_faZbF85m|dMtY43<(uA6?ut;;&{Hd zM0adx95^nKtXx_%!%=OjFP|dT`P;FKJMaE%enT7zg;(rV!B|A zkaFBgU#`ag2%r0wll!(xG$Kdu&*)4giJ}376lgdm5cY``p7&TM`T*S zjXOyOv+^Wm$!BvHz2c3_e7{;bmcWax2fClUqtq_9{ zyVB=bD?|30_nqeFXJ;UqYI;7$_kYf`>#ovIkv{D3w4*$|^AV7`B-lLF7poN!UL6E4 zc&aLNK$#?kF9ya35+XzJntj`RD~bY?r9~Vukbk|Fy{JF8T-(fNmHBkMRK}O-srlGE zf4RmxZz}bcc&>inn{PRI{OrXTws&dN*YH4*1bv&{yt7pu*O9SgUyWE`2DLRC$4X(t zt>R|58X`h*>pgk7RZdZ#uI}M^d@j?khDP9{e8Yq0=K0&scxSUM$_)S1qxGY8`%S-q=j&xjzhDvuBU`DBkxtb_BR>B#BoI`1*E-4$IkvfcSACQpuN zl$Z0ud}p#k>`P=HQN(d;$7R!4QI~Fy%&Ew7UOk-U?ea-Yc|&;(#KL3vCf_RWm?T|q zO*2UA%o)tFwQ2&b`I71PI?5k*fm5E>QHC*b`egnk8brTpPjg0WE&QbiJqDGt$gQ*y zGudK&?KxQDvtg)4>Y0ag?Li7{GwX$pj~dh7TD|scZt-MyZFr)^{FLSc9z?ofirW1L zVbN$K=}c!i+oXA>HAP4PcU2KvB+7U z2@%^Z@zqF)fQgQRj1%gkRtH6g0jv2jd;B!umwN~cYp!UPM+gm~s{0o(Z`hZI>Z>Rg z;*O}cXaUP(&XpNg0M4%O3)J;tJl)PUW*T%zCRPiC^+|Om24w_DMRAUyb!G$$4o7a7 zzd5UCk6>;{m-}yOk`{((V?`#Xw@fnB&2A7q5=3gS=K^}G=NAsI@G|no_mMFB9Wlp0 zFW?=?++cEbu9}__n-Lm@l+j2T4jwUhB(?Rgn)#Rztq0oT9QHNW5MGga^+rwvIr{PD z$n8@S6h-YZJEvwC@NJYmggnPRkBn98Ep{x}9N|kDIF)5)m?4)@j4^J6J5<>Hrdt`Z z;{E}5K|B`*cln8MX!)$3JG^1@Pb<%9r=r`3(}5{<8^XanSBljXu}kdLfc^{iipyE< zOo~cg+6;>7_Es9Xjln0T)d-he9#=%YL7S?d8cXNXONz(jR!#MSEh1WZkU~fSB(Hp$ zuygP}_@=R5#zWCVbGd>i?|4#oLU&4cdUXoL@K<{g!6fe_@3bsP5484u&7!D|=sxO+ z;zjO-`86PGyW_&=eC>`yxBsw?m`)w(_kI^c$>;{!d9kasC0bNixnY{CAa{t;Hs}w= zaxY5yNJ|g1VS_8??g(KO*6!8i2F!Wx0>w>OQqS-P#yQwkrj>s6lTBzt57c?Rs~A3d zP>;cRg{xdE;Dws^lUPsC#@BSktYEob1v_a^^2o3+8~N;HyjXg{fL^r?n+=Qeh&$CM z9Z!lEl6EY<;OULZvWl_#ku^05%kC0Q<4!Ld~LSNtrIl+d%K~*^rS(?r_iJXhdvJ7U*YflwwKJ z0=?U-Qx^Jt5&6jD#$TP7x<~QP+(j+U66=z*RiZjMwMc?GJ!WWHFKLxv8G1u7Zk1#i z=6py?FRoo_BQnJW!GUzU+)5PJsDI<)3e8*yUayd$|3YxwgF$%*kpHoWd=0H!_(cz$ zITFq$!Fi$>A#4`&6E-^j=cPg`^_H_60#Z&4fYrv^P6DKH?}yk>WN$F*6jt#%jm$=`tJrom&PJ!@eHoh2FjJ=4 zwllYE-LW~=a?);gtaqZ*@Y4QBVoE1`^^KMO}o?ju?q?z=M#O~?Ta2C`^6tIBA<)>Nuw+RKD+%B z*Z*O;%YqOvGchxZe(dmEm>}_oLq1yjW#gW;3My%HFTC1YJ+9u$uLwanch|N|O5PjG z$R*_xbu=ehr7yEen}}Y|?tGUvOUg1!rwp$-N!tjk5mrNs>H$3qApu~*gVAWqE#GNjUkpt@~wXBC5^4PY~ zPxIp38{`)iB?iaC1*Vj`t@h+u=5jYska70L3|uC}XQ8%>XD(KgTOvgN2*gfjW2*Ax z3d0{m@BUg7WVws}2{ErV<4a9-TgK;_d>CCis%72v3>FSHE*ef=-d}2R0K9GS^v!~v znALhJ$)BQBth$Gkzhp`#b?kw)l549DKBEUq45@KhpB1Ck^|MkAXOG+z#aht!MlVEl zUrm&i(ENj^Klms?qNc`q**U>`2>C+}JFa@<+d*{#7S zR-SIU6-jhKk~(9;V?)VV%#2!dTjSGhz9C<~gni%HHUe?ZyMl&t?+7xu%#O}8^2Zk4 zWn`@lTU~@54KsOYOg-ShDb?m?MIYOgh7)yp8iMMW@mtztwBisDtj5^!meGrP$k?nU z^UP9eDeY+Aca?HEs>h}Ub0Ei}?h=FTKKfyMUtqhtAytyn+pHHqrB;$u>)zaI#@dRN z-NQ8T@SQ*U)RtAHvCidJ>WNn~$>ItjAA7H+#cmu=3IzsRq0gZMQPj3y+T7{OwnIX; z4LIRf#NyVqJXWJw8u@s2>CeDRA5;DP8rXje0 za9egMNMl_}8rtD)`0Y1+thzbt$LVo5ObC367D2U9X{qei7vb7GE#zxg$BpTjWO-il zMrng?%TYtKxlM!T<}!7plx9H0VL|I)wQqm;N)ZqIG_~I4D$X)^)w0pPB5tN&p%c9l zIfJh=V%pF_2d1g}1hG@q+_fT20d6F$xF0bGJ+;TeQ&Y1st>9UO{;0rwv8 zT{f36QN1RpV??ilYJBV#PPW|U6l{LFH|ut$f`&Im!yL2pJ;o9D3<|gRPYSH`2UF+< zC{!p_G75{KA7q`p>*3!ACrDjZ7TNMJjT1<@b}@=db0L&t=>?%&zs8vN?gn8;aV>(8 z8G9bCn88Y7xL4Jgu*hJ!BYzZc?D+=t|pK+JbmgsqygCFleh(+u#(66iJf7VVdr|F+_MriJLuUINk zC+>Fd(l?6C5%@v~CNRg*I)&cG$Y6_Gc@cM)-nq-phf*?5iHr?30!#S*2C4`O@Acz2 zgSYev#dZ7>{Etf`*TD0<$t?dJ0Z+?D?w07*EuxOgJYyXwz z%S+^1bN}oG!1;j64v)#>5_JH{mh$nPzYjkr1Hu5@5EM-#>TfUc+0Nrm*iIz%$z7qV z`%hjd?@r$lDcTT2Cx7^G=HkLHL&w+p)y-JjRLncLLmC$B-aK{m*|;VjA789D0Gq<-^pJ(Hb#`UhI4us+ZhPk;N-wJXxE z(e~p7J^?(j_(`@6hF3fgM!v7LF?>rQm{Er}Hb@%#u&}GrGKmIh7m}&jZ&r%=ZO(WC} zve4;6(qFPv0}E0_<>JX+5P1>qdM@w6=?xeSs0`H18+t42t1J!60Ewvikr!{p)8Xf8 zEkAx?z0&IlRMa;m?nqb@)v5f{kaks1(BTwPYI1ub?oCh6?DrgC2$LI$Txgv5firjo zypm=3{@bw_qbHvELuB&)-kh_T{di+rS;SEt*GWS%V6#1 za=e1@dOM|9vmPDa^J>GL9+O7Kos&j1#`!*E=KP0Y-j+@G?w{!X$52Ks{geeERo^>7 z&=wjBqH@ccS`}8gRzK(;4E(VkIdEkEP%5gX(HAoYnr!j2%Fw2xxrb$Tm3+xeG zta;$;nr9))vvA#di|c%3TIwNWiEKQL9!D>! z)o!(AOUD^?HEZ11?D%&ni@5Fyp%wchl}BjVe4yF(c0{SkbOQeVk=Ou_kZWiHb!wQOJrL8Bl(RSmb8jd@~2ZFHreNHPMVl~8B$Q;09^!W1EmbEMQjM8 zv7p?8iJ+Vy`8MCPU8J;x0awrthw0GmkEb3>is)0Fx=P9+EgrG?2Cj<{te;y?9Fe3F z$FerMxy-|d;v-WHs2OfCJ1Ny}=7w|5sVNz8EncR9%ohC<;W>*TH)X9EM&#Fc3xe}> z5zP-W%>(*zTl&xW6^zh;DQ8txFz4Z}+Xhl^T+Oo^U+G^y07yr;;hTZ@ZbY@#4Z~KHTS_mAEX#GPZ1VzaHpkPsWxksr-k9%M31 z30iSWWpma>5u+Ypw3+p=(~0f(=R*DBScATE6O}VU?oYv?$H$#OZuaooNHGtqx$*hL z{7HZ)pL$sL;Dcj5w`hhilL*>ZkvO-kNdFAX{zh!X}+mi=7_wQGi#%q_s$BqRy`c`F(`sJ-!-K@O1_3&cu7f_ zH{GaRY0Bor^QW+c44EUh45>*l@BeHJft^xOmfS8|N;+(rbt$r8<`ML$W%JslO6H7% z&hl?3q9uBaQ~+Ex2F*<(IGe3A$3xN0MtlCCHg5w;G3e!-;?o8fQ7;gia}yXpx*>|X zOwH4VLb4;eC{Z6<+to-ggldX|=caY%vLgPRC#JNYxBJhaaaME}ADY7*_Z21TX3J>= zZ-?8|oPKo5&1Av6Toegf@Gk%JG!=+8HF>7!f*YR5^I5t5`KNV}i-arn9& zwHW$32UK~(c=d$$m;mTA3%O~=KE{)jSM6*91=e5?vN|kF?VHJ1RLN{S&m@YM&A@vV?Vgk+vaE-rm?*F86$Q zHk$c~*#+j$bq1Q5s<5T1<_(*d;m(qdm_Y%k-m(p4b=<~_hKr_d8ZW$~H)i z?fv(g$TOAI23FmXfjaF<=)SBy2EJ;=29>LkQ~twMOK$gv{ZTd~8zN3a>G#mX@zdoc$JiL^-Mb)W1Du z@)gPmqPG$UYS~liwq#{aVOHYp<7CR9D`QpS+Hw0@iRca(>>uf+qBg7|1n2rLVL5&o z-6fj7UFfIT2bA%nPnFLkLHPBi^A<25bOm#SbMQBqE+M$9na8B`gh@VGDNZJ-1<-Ux zHMQ4s(@$T(`Q4#lo_hhUjH? z;$*vSYoJe8(M28IJl3kLp~97mXJ+ms%gP1*Y;cr0b;Mcu4S|58i%_7Bn1e0f^XHl; zDBOyP8>O{C1kVUF-y$qWkqS2-q)l}%P$KDs_b(g zu1~xWl5GFS%BF)9KkCyR8Pj zU*t@bRG>023(6n@k{suPmp{;ixobOF@wd;7ceB;JO0MFMwU*lY$E*=_oJn6iW zlalzzVM@;%3#-#rK|ulWK%|Mxgy`6K(opr9YcJu+m1o}d_{Wkw;;7pK8A2l2V~$su z7))2G#prwKWC^nHTwE4U<9daZ+n@jVPX`7_e0iu3iwb6|l5i~dk(Vmr%cZM1@~SrI z`GTAyCn*IqnnM_h&E-KyEJ&)0+M}pl=*&hIIE6hYM%w)i1(o;?Vp=l>Mls3ZUSJT! z#fH*Q&kJJWaa1(-Hg_w=PQ^-KvJhBUjMtdLs2P)#(q9ZV@HZ=<>ZpuwKi0>N4&L2K zx^GI-I@c_Z2d5LTwq4FnmXgk& zSISnUViMxvW5<*&Czm@oVa*j-RkM^Rg&P%C0XI9ce%$*{1fPm|Mum)P^4FM-YEJNm zZ%m803d7NV{?dHmYcRu>v2?vT7=o~+PqX-=VR6r@1=snMYo*dx-N@ojGRmwLsH)j^(>~ilo{M!55#f`KcSRxLsqUaTd3T zsjg`mU6!~idGR~-xCX&h>kDA&7hU5Es2M^e{WITqNLA?|oSnz=tu$})gQH`LC;ats z2~A-XKu>Z*^fED>!Tx`Le*YzZH+58%By*qG|z!5J}Dc}=zQ|$zB{-$ ztyQA1Hf1rt@hptba#O!c3$ux_?c-+Q3137w9C4_my?+ zd~uDqMp7lWK~1VM3W|ku1%ht1>eoq$Lwl5r9`~&5%C7;1s!1G5i>9tMgGde}RAS8E z)1D5P+O$l^dJ48^R7yZ95NgA)1ShO0gx4`UwlR_VgyQqmzTzL5_l0%N)2}EP)6F=y z-dPxwkO1)9o?ZZEQd6K}A-080k2p?dfVq~r`!aS82(Ub>i8Gl)L&Q09-!cQnph>Z> z8xJ?9RpE(9VTrO2 zR?eh1M@y5{{NdhVMl+jbe=%-b5o)E=+vzmaV2$BISce-BQA%&ccGI#V#e?S(w;Wzw z=xJP=Sd39MeGTp~sKcMn(M%&9ozTs0RjF_u%-a~gh80YfUd6$}odJqFHl#jbC) zj)>Z{d*wrha=e!n0RyE%nq{dYE&J`8NHUtuGMcZGlBL#wNPHRt}Nc)eJh5?ZtZZM5EN>DgDh zgpXK29Dt8ecM{f9yQ*%ZZdsg2|0wy8WZHupRjUy{ZKnJlL+}_1xj{=)ZX)C5MS{8?!^ggBW ziT!(m@jIhZFe4J@XvVSS3Ks^ooZCn%<9zsI*!^(FazTIks3>R%6YGG6VNc3^O!cVOpdjQiG>9F1jCT zYPaktcIPE0aVR-+_tHph!Kj;{`Fj7IHO=gc521A|t$$gJ8FfPc_MJ$?CF9X|LI|1Z z4)Dq52yD;Ho66)ljQ!At!`j=g&U%ZaHs;eGXO=eIihx_gc#?op2QDa|%g#;cNE1!G zq)|%g=o~3Unk6U;Os(;a+xm9qBQ8(CCdn z12mSmwvkwCTh(f72SBTdJnSUTUk8-PztpvfXGZuJ6CwAw6>l!W73jLI?ZI7<-;Z%b z^rghM&1SKm1V#Nu&2Rs4#QNi56Cx}ashfZDZF?dqP%hyiA6(P69qCd$a(g<4FlbT& z(U`@?>Z96YswuApg$_;h;c)(LHA_fgb8X^_h^rN>Yn(xp?ycEhiB=$6E8F7v(_!k8 z8k_X$E{2;)m_V|nSx{1ARv-F#lQ(9G@}93WM-l?{QDgTt7}G~fv((iRpUX_4$)N)B zXNG9rAvFEru6l|I6?~;&g0XFa;T%<3rVIc$=O1V|M?ItdoZ8ZVn5o{7)YzQsPt4WJ z`t9#=+x3-4Wt^6NuBZ_)jN95Pbo#hVeUBDfMfJcgaX^3?bKjbaGiQ}m4Pe`>6Hvf& zJ%X6jrtZQ&bRuXZp%I`20Mk|_HLnmt6pVjWa&hmi-!$S|LzIjGvy=7WfV9$AT|^o-_E3pI zVy3mnOzQq>;+|uXql8ebQh(TM8>GAO^Hfp?C3tywIK$Scq#J=OutjG|qxq6ky0Ay1 zRlI*?MSaVVLo}pRy=mU4FJgISmp_U_wr%Q|mZ5cDTb?SS+)@1X&|#RtBs^Hcjk{t> zkmDMWVh*x-LX|X#oK(UtSkAa2kt2w&aKSsZSB@WKJ*dd< z+oh})887KvN?M@V8OC|l-7=yNfET3Lkm*GiE|Qt0Smb$|OTw(1#qMGaW*X5ra#qC< zpmpl%Nw3Q5j~p7o;j;7NwX5}>T~Jv3QfPXZVpM2s7B!w3{RI~tH(u#y!I_69eHcD= zTz47IcMRO)-(xg1WtB--bc*iAXHtBl8u<8S zjct`(`|*=$;N2Xp7=j!npqMq!)m1HnsC%hoVD^`=jgKaQ@S@Era;lDBMCCt+|V z1S5v^d8^9`Kc!2e1_q{>ECh^_JEkn#p!;=9Vnk$^{5(K9?oGJi2$pQYQO`TJh9kJHrx!vfdj>F?hZtB8^cR$J`QPf|Wk#0*`wUY1fgc7itL7hB}Ayr0kT7hJM=ZTVk+Kf?vVVz_Z{3r$Ud!C*zHC!|wK8c;h$y1QyX zo8-fLtxuu``BWwjl|mH6W(g#}Z{yQyyS8l?uS=Zk*jCu9U<+Q;s-{D^$$CL#g!evN z(lmDC^~2mT)HJW%C@N!yGn}uDVYCG)-pW&r9}`OE^;;fxdofEarbsbEyFCeq*1)Ad zI=sNmv_mv8t+nXphjqtGNK3r>QT1vbxr^$~PK;+sawSz6bdDTa;e~x)s&b>SDf)tk z&+$KkTHHlw8Gd~g85stC&#!R3kV-~$;)yf*^bBBVO7i`;srwxNXH)lynONBVWv0GP zw2VbJ!^gnW7Yt74Aj5f`oFM%@CPa=Sf0IY3$a3SrUSOodKt~pzB;1#UGvc;b-N|~7 zld=&0HGd@@QS69WD69t90ETsAS`OO@(O$d+z0s*JsXfp2!s%RGoKr0CuD+TiVFMR* zYVpo|CmOODvAKSqlpcS%ExqMq&x_~`{*-MeouQlWlfe9*uG*_eX|=~Hi^T^cD@|-Y z0M!X^n}uGN`s0+WIBudKzk>`3yyi2&2Mjh)USoP258j)0ZjAb%#Xm*NS9Uc4q9Gi#Nk;c`SxfKm_tex-&XAe%z5Lj+`yI@xmX)28 zD-U@lJl5C>VKuQWQ(s2)8wf#rV3)#GB46tx`GtBGtKb0f@G;(GzJ>sRjusRop&pq& z9m|Cuwdj^XQq&+Y%Ey}EJ>6c_dG|!|r4M8ovSUl=XXSkCf{J!EkyIb`y+*q296it7Nm-$@FPnO4-cRn4xY0MsVe(P%&nyP8z!?5=TC|FR)PEM6R@B< zbP#TWmQ0XLF&A$dqM`N-pY1AX-*X8Pg2ME3$Zayl(JYf;{n6^G^XnOKRWraOF%@5e zj~Nmz%oyPA7m^-6luj0ETNuZE0t8y?L@4bhiEs3`fsSS)oqx|%sMo1j870E4%pr-h z6gq^^s@ds?gm*u~{`fThW^?&(F0a2#YyT>jfAP*S{;i1rFTHbrTjH4BJaqq;TyO8* rlZzsu!M=O<^iJ{LU0wgpeD~&qGO%}awKp+EWMTv&l97qXi6Z_#FstrE literal 0 HcmV?d00001 diff --git a/tests/pom.xml b/tests/pom.xml index 93e69fda49..d703e19874 100644 --- a/tests/pom.xml +++ b/tests/pom.xml @@ -17,22 +17,6 @@ Spring Cloud Contract Tests Spring Cloud Contract Tests - - samples-messaging-camel - samples-messaging-stream - samples-messaging-integration - samples-messaging-amqp - spring-cloud-contract-stub-runner-camel - spring-cloud-contract-stub-runner-boot-eureka - spring-cloud-contract-stub-runner-boot-zookeeper - spring-cloud-contract-stub-runner-context-path - spring-cloud-contract-stub-runner-moco-contract-jar - spring-cloud-contract-stub-runner-moco - spring-cloud-contract-stub-runner-integration - spring-cloud-contract-stub-runner-stream - spring-cloud-contract-stub-runner-amqp - - @@ -52,4 +36,51 @@ + + + CI + + + env.CI + + + + samples-messaging-camel + samples-messaging-stream + samples-messaging-integration + samples-messaging-amqp + spring-cloud-contract-stub-runner-camel + spring-cloud-contract-stub-runner-boot-eureka + spring-cloud-contract-stub-runner-boot-zookeeper + spring-cloud-contract-stub-runner-context-path + spring-cloud-contract-stub-runner-integration + spring-cloud-contract-stub-runner-stream + spring-cloud-contract-stub-runner-amqp + + + + default + + + !env.CI + + + + samples-messaging-camel + samples-messaging-stream + samples-messaging-integration + samples-messaging-amqp + spring-cloud-contract-stub-runner-camel + spring-cloud-contract-stub-runner-boot-eureka + spring-cloud-contract-stub-runner-boot-zookeeper + spring-cloud-contract-stub-runner-context-path + spring-cloud-contract-stub-runner-moco-contract-jar + spring-cloud-contract-stub-runner-moco + spring-cloud-contract-stub-runner-integration + spring-cloud-contract-stub-runner-stream + spring-cloud-contract-stub-runner-amqp + + + +