diff --git a/spring-cloud-contract-verifier/pom.xml b/spring-cloud-contract-verifier/pom.xml index d25eed7ee3..dd4909600b 100644 --- a/spring-cloud-contract-verifier/pom.xml +++ b/spring-cloud-contract-verifier/pom.xml @@ -106,6 +106,22 @@ snakeyaml test + + com.jayway.restassured + spring-mock-mvc + test + + + org.springframework.boot + spring-boot-starter-jersey + test + + + org.mdkt.compiler + InMemoryJavaCompiler + 1.2 + test + 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 index 42e6916aba..11181a6fdf 100644 --- 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 @@ -121,7 +121,7 @@ abstract class JUnitMethodBodyBuilder extends RequestProcessingMethodBodyBuilder @Override protected String getSimpleResponseBodyString(String responseString) { - return "Object responseBody = ($responseString);" + return "String responseBody = $responseString;" } @Override 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 index 53d2e2e55b..4157874499 100644 --- 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 @@ -18,6 +18,7 @@ package org.springframework.cloud.contract.verifier.builder import groovy.transform.PackageScope import groovy.transform.TypeChecked +import org.apache.commons.lang3.StringEscapeUtils import org.springframework.cloud.contract.spec.internal.* import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties import org.springframework.cloud.contract.verifier.util.ContentType @@ -262,9 +263,13 @@ abstract class MethodBodyBuilder { ContentType contentType = getResponseContentType() Object convertedResponseBody = responseBody if (convertedResponseBody instanceof GString) { - convertedResponseBody = extractValue(convertedResponseBody, contentType, { DslProperty dslProperty -> dslProperty.serverValue }) + convertedResponseBody = extractValue(convertedResponseBody, contentType, { Object o -> o instanceof DslProperty ? o.serverValue : o }) + } + if (contentType != ContentType.TEXT) { + convertedResponseBody = MapConverter.getTestSideValues(convertedResponseBody) + } else { + convertedResponseBody = StringEscapeUtils.escapeJava(convertedResponseBody.toString()) } - convertedResponseBody = MapConverter.getTestSideValues(convertedResponseBody) if (contentType == ContentType.JSON) { appendJsonPath(bb, getResponseAsString()) JsonPaths jsonPaths = new JsonToJsonPathsConverter(configProperties).transformToJsonPathWithTestsSideValues(convertedResponseBody) 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 index e32914eec3..1c97ccd950 100644 --- 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 @@ -28,6 +28,7 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig import java.util.regex.Pattern +import static org.apache.commons.lang3.StringEscapeUtils.escapeJava import static org.springframework.cloud.contract.verifier.util.ContentUtils.getGroovyMultipartFileParameterContent /** @@ -152,7 +153,7 @@ abstract class SpockMethodRequestProcessingBodyBuilder extends RequestProcessing } protected String patternComparison(String pattern) { - return "==~ java.util.regex.Pattern.compile('$pattern')" + String converted = escapeJava(convertUnicodeEscapesIfRequired(pattern)) + return "==~ java.util.regex.Pattern.compile('${converted}')" } - } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/BaseWireMockStubStrategy.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/BaseWireMockStubStrategy.groovy index 1226c39bf1..ca8fad8475 100755 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/BaseWireMockStubStrategy.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/dsl/wiremock/BaseWireMockStubStrategy.groovy @@ -91,7 +91,7 @@ abstract class BaseWireMockStubStrategy { * For the given {@link ContentType} returns the String version of the body */ String parseBody(GString value, ContentType contentType) { - Object processedValue = extractValue(value, contentType, { DslProperty dslProperty -> dslProperty.clientValue }) + Object processedValue = extractValue(value, contentType, { Object o -> o instanceof DslProperty ? o.clientValue : o }) if (processedValue instanceof GString) { return parseBody(processedValue.toString(), contentType) } diff --git a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentType.groovy b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentType.groovy index 48887c3744..4b7242f912 100644 --- a/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentType.groovy +++ b/spring-cloud-contract-verifier/src/main/groovy/org/springframework/cloud/contract/verifier/util/ContentType.groovy @@ -25,6 +25,7 @@ enum ContentType { JSON("application/json"), XML("application/xml"), + TEXT("text/plain"), UNKNOWN("application/octet-stream") final String mimeType 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 8b70559c97..0e39559d13 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 @@ -70,6 +70,9 @@ class ContentUtils { if (bodyAsValue.isEmpty()){ return bodyAsValue } + if (contentType == ContentType.TEXT) { + return extractValueForText(bodyAsValue, valueProvider) + } if (contentType == ContentType.JSON) { return extractValueForJSON(bodyAsValue, valueProvider) } @@ -154,6 +157,14 @@ class ContentUtils { return extractValue(bodyAsValue, ContentType.UNKNOWN, valueProvider) } + private static String extractValueForText(GString bodyAsValue, Closure valueProvider) { + GString transformedString = new GStringImpl( + bodyAsValue.values.collect { valueProvider(it) } as String[], + bodyAsValue.strings.clone() as String[] + ) + return transformedString.toString() + } + private static Object extractValueForJSON(GString bodyAsValue, Closure valueProvider) { GString transformedString = new GStringImpl( bodyAsValue.values.collect { transformJSONStringValue(it, valueProvider) } as String[], @@ -272,6 +283,9 @@ class ContentUtils { if (content?.endsWith("xml")) { return ContentType.XML } + if (content?.contains("text")) { + return ContentType.TEXT + } return ContentType.UNKNOWN } 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 4fcc75edba..bafef06b5d 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 @@ -21,6 +21,7 @@ import org.springframework.cloud.contract.verifier.config.ContractVerifierConfig import org.springframework.cloud.contract.verifier.dsl.WireMockStubVerifier import org.springframework.cloud.contract.verifier.dsl.wiremock.WireMockStubStrategy import org.springframework.cloud.contract.verifier.file.ContractMetadata +import org.springframework.cloud.contract.verifier.util.SyntaxChecker import spock.lang.Issue import spock.lang.Shared import spock.lang.Specification @@ -55,6 +56,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -88,6 +91,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().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()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -123,6 +128,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().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()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -161,6 +168,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().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()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -190,6 +199,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | bodyString "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | """entity('{\"items\":[\"HOP\"]}', 'application/json')""" @@ -219,6 +230,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | bodyString "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | """entity('property1=VAL1', 'application/octet-stream')""" @@ -252,6 +265,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("property2").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -284,6 +299,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property1").contains("property3").isEqualTo("test2")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -316,6 +333,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -353,6 +372,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -383,6 +404,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -411,6 +434,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains(requestString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | requestString "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | "request('text/plain')" @@ -444,6 +469,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub !blockBuilder.toString().contains("""Content Type""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | requestStrings "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | ["""entity('', 'text/plain')""", """header('Timer', '123')"""] @@ -498,6 +525,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub test.contains(modifyStringIfRequired.call("""assertThatJson(parsedJson).field("property2").isEqualTo("b")""")) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | modifyStringIfRequired "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | { String paramString -> paramString } @@ -553,6 +582,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub test.contains(modifyStringIfRequired.call("""assertThatJson(parsedJson).field("property2").isEqualTo("b")""")) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | modifyStringIfRequired "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | { String paramString -> paramString } @@ -581,6 +612,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub test.contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | bodyString "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | "entity('', 'application/octet-stream')" @@ -609,10 +642,12 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub test.contains(bodyEvaluationString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | "String responseAsString = response.readEntity(String)" | 'responseBody == "test"' - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } | 'Object responseBody = (responseAsString);' | 'assertThat(responseBody).isEqualTo("test");' + "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } | 'String responseBody = responseAsString;' | 'assertThat(responseBody).isEqualTo("test");' } @Issue('#171') @@ -642,6 +677,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub test.contains(methodString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | methodString "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | ".method('GET')" @@ -712,6 +749,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub stripped(test) == stripped(expectedResponse) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompileJava(blockBuilder.toString()) } @Issue('#85') @@ -758,10 +797,12 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDsl, properties) BlockBuilder blockBuilder = new BlockBuilder(" ") when: - builder.then(blockBuilder) + builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: test.contains("assertThat(responseBody).matches(\".*\");") + and: + SyntaxChecker.tryToCompileJava(blockBuilder.toString()) } @Issue('#150') @@ -785,6 +826,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub def test = blockBuilder.toString() then: test.contains("responseBody ==~ java.util.regex.Pattern.compile('.*')") + and: + SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } @Issue('#150') @@ -804,7 +847,7 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub MethodBodyBuilder builder = new JaxRsClientJUnitMethodBodyBuilder(contractDsl, properties) BlockBuilder blockBuilder = new BlockBuilder(" ") when: - builder.then(blockBuilder) + builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: test.contains("foo(responseBody);") @@ -831,6 +874,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub def test = blockBuilder.toString() then: test.contains("foo(responseBody)") + and: + SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } def "should allow c/p version of consumer producer"() { @@ -864,6 +909,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -924,6 +971,8 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub test.contains('assertThatJson(parsedJson).field("ip").matches("([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])")') test.contains('assertThatJson(parsedJson).field("uuid").matches("[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}")') !test.contains('cursor') + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -938,35 +987,37 @@ class JaxRsClientMethodBuilderSpec extends Specification implements WireMockStub @Unroll def "should resolve Optional object when used in query parameters for [#methodBuilderName]"() { given: - Contract contractDsl = Contract.make { - request { - method 'GET' - urlPath('/blacklist') { - queryParameters { - parameter 'isActive': value(consumer(optional(regex('(true|false)')))) - parameter 'limit': value(consumer(optional(regex('([0-9]{1,10})')))) - parameter 'offset': value(consumer(optional(regex('([0-9]{1,10})')))) + Contract contractDsl = Contract.make { + request { + method 'GET' + urlPath('/blacklist') { + queryParameters { + parameter 'isActive': value(consumer(optional(regex('(true|false)')))) + parameter 'limit': value(consumer(optional(regex('([0-9]{1,10})')))) + parameter 'offset': value(consumer(optional(regex('([0-9]{1,10})')))) + } + } + headers { + header 'Content-Type': 'application/json' } } - headers { - header 'Content-Type': 'application/json' + response { + status(200) } } - response { - status(200) - } - } - MethodBodyBuilder builder = methodBuilder(contractDsl) - BlockBuilder blockBuilder = new BlockBuilder(" ") + MethodBodyBuilder builder = methodBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") when: - builder.appendTo(blockBuilder) - def test = blockBuilder.toString() + builder.appendTo(blockBuilder) + def test = blockBuilder.toString() then: - !test.contains('org.springframework.cloud.contract.spec.internal.OptionalProperty') - test.contains('(([0-9]{1,10}))?') + !test.contains('org.springframework.cloud.contract.spec.internal.OptionalProperty') + test.contains('(([0-9]{1,10}))?') + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: - methodBuilderName | methodBuilder - "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } - "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } + methodBuilderName | methodBuilder + "JaxRsClientSpockMethodRequestProcessingBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientSpockMethodRequestProcessingBodyBuilder(dsl, properties) } + "JaxRsClientJUnitMethodBodyBuilder" | { org.springframework.cloud.contract.spec.Contract dsl -> new JaxRsClientJUnitMethodBodyBuilder(dsl, properties) } } } diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy index c22faa9c41..3373c6a535 100644 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MockMvcMethodBodyBuilderSpec.groovy @@ -19,6 +19,7 @@ package org.springframework.cloud.contract.verifier.builder import org.springframework.cloud.contract.spec.Contract import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties import org.springframework.cloud.contract.verifier.dsl.WireMockStubVerifier +import org.springframework.cloud.contract.verifier.util.SyntaxChecker import spock.lang.Issue import spock.lang.Shared import spock.lang.Specification @@ -102,6 +103,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } } + @Unroll def "should generate assertions for simple response body with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -126,6 +128,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property2").isEqualTo("b")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -133,6 +137,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } @Issue("#187") + @Unroll def "should generate assertions for null and boolean values with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -159,6 +164,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property3").isEqualTo(false)""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -166,6 +173,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } @Issue("#79") + @Unroll def "should generate assertions for simple response body constructed from map with a list with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -194,6 +202,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("b").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -202,6 +212,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub @Issue("#79") @RestoreSystemProperties + @Unroll def "should generate assertions for simple response body constructed from map with a list with #methodBuilderName with array size check"() { given: System.setProperty('spring.cloud.contract.verifier.assert.size', 'true') @@ -232,6 +243,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property2").contains("b").isEqualTo("sthElse")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -239,6 +252,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } @Issue("#82") + @Unroll def "should generate proper request when body constructed from map with a list #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -261,6 +275,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | bodyString "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | """.body('''{\"items\":[\"HOP\"]}''')""" @@ -268,6 +284,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } @Issue("#88") + @Unroll def "should generate proper request when body constructed from GString with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -289,6 +306,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub then: blockBuilder.toString().contains(bodyString) and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + and: stubMappingIsValidWireMockStub(contractDsl) where: methodBuilderName | methodBuilder | bodyString @@ -297,6 +316,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } @Issue("185") + @Unroll def "should generate assertions for a response body containing map with integers as keys with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -323,12 +343,15 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property").field(14).isEqualTo(0.0)""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } + @Unroll def "should generate assertions for array in response body with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -356,12 +379,15 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).array().contains("property1").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } + @Unroll def "should generate assertions for array inside response body element with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -388,12 +414,15 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).array("property1").contains("property3").isEqualTo("test2")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } + @Unroll def "should generate assertions for nested objects in response body with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -420,12 +449,15 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } + @Unroll def "should generate regex assertions for map objects in response body with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -456,12 +488,15 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } + @Unroll def "should generate regex assertions for string objects in response body with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -488,6 +523,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property1").isEqualTo("a")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -495,6 +532,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } @Issue(["#126", "#143"]) + @Unroll def "should generate escaped regex assertions for string objects in response body with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -520,12 +558,15 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub blockBuilder.toString().contains("""assertThatJson(parsedJson).field("property").matches("\\\\d+")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } + @Unroll def "should generate a call with an url path and query parameters with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -575,6 +616,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub test.contains('assertThatJson(parsedJson).field("property2").isEqualTo("b")') and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -582,6 +625,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } @Issue('#169') + @Unroll def "should generate a call with an url path and query parameters with url containing a pattern with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -631,12 +675,15 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub test.contains('assertThatJson(parsedJson).field("property2").isEqualTo("b")') and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } + @Unroll def "should generate test for empty body with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -658,12 +705,15 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub test.contains(bodyString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | bodyString "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | ".body('''''')" "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | ".body(\"\\\"\\\"\")" } + @Unroll def "should generate test for String in response body with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -686,13 +736,16 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub test.contains(bodyEvaluationString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | bodyDefinitionString | bodyEvaluationString "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | 'def responseBody = (response.body.asString())' | 'responseBody == "test"' - "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | 'Object responseBody = (response.getBody().asString());' | 'assertThat(responseBody).isEqualTo("test");' + "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | 'String responseBody = response.getBody().asString();' | 'assertThat(responseBody).isEqualTo("test");' } @Issue('113') + @Unroll def "should generate regex test for String in response header with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -725,6 +778,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub test.contains(headerEvaluationString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | headerEvaluationString "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | '''response.header('Location') ==~ java.util.regex.Pattern.compile('http://localhost/partners/[0-9]+/users/[0-9]+')''' @@ -732,6 +787,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } @Issue('115') + @Unroll def "should generate regex with helper method with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -764,12 +820,15 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub test.contains(headerEvaluationString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: - methodBuilderName | methodBuilder | headerEvaluationString - "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | '''response.header('Location') ==~ java.util.regex.Pattern.compile('^((http[s]?|ftp):\\/)\\/?([^:\\/\\s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+')''' + methodBuilderName | methodBuilder | headerEvaluationString + "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | '''response.header('Location') ==~ java.util.regex.Pattern.compile('^((http[s]?|ftp):/)/?([^:/s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+')''' "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | 'assertThat(response.header("Location")).matches("^((http[s]?|ftp):/)/?([^:/s]+)(:[0-9]{1,5})?/partners/[0-9]+/users/[0-9]+");' } + @Unroll def "should work with more complex stuff and jsonpaths with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -805,12 +864,15 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub test.contains("""assertThatJson(parsedJson).array("errors").contains("message").isEqualTo("incorrect_format")""") and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } + @Unroll def "should work properly with GString url with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -838,12 +900,15 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub test.contains('''/partners/11/agents/11/customers/09665703Z''') and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } + @Unroll def "should resolve properties in GString with regular expression with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -877,6 +942,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub def test = blockBuilder.toString() 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,4}\\\\\\\\]")""") + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -897,6 +964,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub !test.contains('''REGEXP''') !test.contains('''OPTIONAL''') !test.contains('''OptionalProperty''') + and: + SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) where: contractDsl << [dslWithOptionals, dslWithOptionalsInString] } @@ -915,11 +984,14 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub !test.contains('''REGEXP''') !test.contains('''OPTIONAL''') !test.contains('''OptionalProperty''') + and: + SyntaxChecker.tryToCompileJava(blockBuilder.toString()) where: contractDsl << [dslWithOptionals, dslWithOptionalsInString] } @Issue('72') + @Unroll def "should make the execute method work with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -972,6 +1044,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | ['''assertThatRejectionReasonIsNull(parsedJson.read("$.rejectionReason"))''', '''assertThatLocationIsNull(response.header("Location"))'''] } + @Unroll def "should support inner map and list definitions with #methodBuilderName"() { given: @@ -1033,6 +1106,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub test.contains bodyString !test.contains("clientValue") !test.contains("cursor") + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | bodyString "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | '"street":"Light Street"' @@ -1040,6 +1115,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } + @Unroll def "shouldn't generate unicode escape characters with #methodBuilderName"() { given: Pattern ONLY_ALPHA_UNICODE = Pattern.compile(/[\p{L}]*/) @@ -1072,6 +1148,8 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub def test = blockBuilder.toString() then: !test.contains("\\u041f") + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -1079,6 +1157,7 @@ class MockMvcMethodBodyBuilderSpec extends Specification implements WireMockStub } @Issue('177') + @Unroll def "should generate proper test code when having multiline body with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -1099,6 +1178,8 @@ World.''') def test = blockBuilder.toString() then: test.contains(bodyString) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | bodyString "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | """'''hello, @@ -1107,6 +1188,7 @@ World.'''""" } @Issue('180') + @Unroll def "should generate proper test code when having multipart parameters with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -1135,6 +1217,8 @@ World.'''""" for (String requestString : requestStrings) { test.contains(requestString) } + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | requestStrings "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | ["""'content-type', 'multipart/form-data;boundary=AaB03x'""", @@ -1148,6 +1232,7 @@ World.'''""" } @Issue('180') + @Unroll def "should generate proper test code when having multipart parameters with named as map with #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -1173,6 +1258,8 @@ World.'''""" def test = blockBuilder.toString() then: test.contains('.multiPart') + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -1211,6 +1298,8 @@ World.'''""" def test = blockBuilder.toString() then: test.contains('''assertThatJson(parsedJson).array("authorities").arrayField().matches("^[a-zA-Z0-9_\\\\- ]+\\$").value()''') + and: + SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } @Issue('#216') @@ -1245,9 +1334,12 @@ World.'''""" def test = blockBuilder.toString() then: test.contains('''assertThatJson(parsedJson).array("authorities").arrayField().matches("^[a-zA-Z0-9_\\\\- ]+$").value()''') + and: + SyntaxChecker.tryToCompileJava(blockBuilder.toString()) } - def "should work with execution property"() { + @Unroll + def "should work with execution property with #methodBuilderName"() { given: Contract contractDsl = Contract.make { request { @@ -1306,9 +1398,12 @@ World.'''""" def test = blockBuilder.toString() then: test.contains('assertThatJson(parsedJson).array().contains("id").matches("[0-9]+")') + and: + SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } @Issue('266') + @Unroll def "should generate proper test code with top level array using #methodBuilderName"() { given: Contract contractDsl = Contract.make { @@ -1327,7 +1422,7 @@ World.'''""" MethodBodyBuilder builder = methodBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: - builder.then(blockBuilder) + builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: test.contains('assertThatJson(parsedJson).arrayField().contains("Java8").value()') @@ -1335,6 +1430,8 @@ World.'''""" test.contains('assertThatJson(parsedJson).arrayField().contains("Java").value()') test.contains('assertThatJson(parsedJson).arrayField().contains("Stream").value()') test.contains('assertThatJson(parsedJson).arrayField().contains("SpringBoot").value()') + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -1343,6 +1440,7 @@ World.'''""" @Issue('266') @RestoreSystemProperties + @Unroll def "should generate proper test code with top level array using #methodBuilderName with array size check"() { given: System.setProperty('spring.cloud.contract.verifier.assert.size', 'true') @@ -1362,7 +1460,7 @@ World.'''""" MethodBodyBuilder builder = methodBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: - builder.then(blockBuilder) + builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: test.contains('assertThatJson(parsedJson).hasSize(5)') @@ -1371,6 +1469,8 @@ World.'''""" test.contains('assertThatJson(parsedJson).arrayField().contains("Java").value()') test.contains('assertThatJson(parsedJson).arrayField().contains("Stream").value()') test.contains('assertThatJson(parsedJson).arrayField().contains("SpringBoot").value()') + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -1396,20 +1496,22 @@ World.'''""" MethodBodyBuilder builder = methodBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: - builder.then(blockBuilder) + builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: test.contains('assertThatJson(parsedJson).array().arrayField().isEqualTo("Programming").value()') test.contains('assertThatJson(parsedJson).array().arrayField().isEqualTo("Java").value()') test.contains('assertThatJson(parsedJson).array().arrayField().isEqualTo("Spring").value()') test.contains('assertThatJson(parsedJson).array().arrayField().isEqualTo("Boot").value()') + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } - - @Issue('47') + + @Issue('47') def "should generate async body when async flag set in response"() { given: Contract contractDsl = Contract.make { @@ -1431,6 +1533,8 @@ World.'''""" test.contains(bodyDefinitionString) and: stubMappingIsValidWireMockStub(contractDsl) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: methodBuilderName | methodBuilder | bodyDefinitionString "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | '.when().async()' @@ -1459,11 +1563,13 @@ World.'''""" MethodBodyBuilder builder = methodBuilder(contractDsl) BlockBuilder blockBuilder = new BlockBuilder(" ") when: - builder.then(blockBuilder) + builder.appendTo(blockBuilder) def test = blockBuilder.toString() 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()) where: methodBuilderName | methodBuilder "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } @@ -1486,10 +1592,12 @@ World.'''""" MethodBodyBuilder builder = new MockMvcSpockMethodRequestProcessingBodyBuilder(contractDsl, properties) BlockBuilder blockBuilder = new BlockBuilder(" ") when: - builder.then(blockBuilder) + builder.appendTo(blockBuilder) def test = blockBuilder.toString() then: test.contains('assertThatJson(parsedJson).field("message").matches("^(?!\\\\s*\\$).+")') + and: + SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } Contract dslForDocs = @@ -1580,6 +1688,8 @@ World.'''""" 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(blockBuilder.toString()) } @Issue('#85') @@ -1607,6 +1717,8 @@ World.'''""" def test = blockBuilder.toString() then: test.contains('assertThatRejectionReasonIsNull(parsedJson.read(\'$.rejectionReason.title\'))') + and: + SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } @Issue('#111') @@ -1637,6 +1749,8 @@ World.'''""" def test = blockBuilder.toString() then: test.contains('.header("authorization", getOAuthTokenHeader())') + and: + SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } @Issue('#150') @@ -1660,6 +1774,8 @@ World.'''""" def test = blockBuilder.toString() then: test.contains("responseBody ==~ java.util.regex.Pattern.compile('.*')") + and: + SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } @Issue('#150') @@ -1683,6 +1799,8 @@ World.'''""" def test = blockBuilder.toString() then: test.contains("foo(responseBody)") + and: + SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } @Issue('#149') @@ -1713,6 +1831,8 @@ World.'''""" def test = blockBuilder.toString() then: test.contains('.header("authorization", getOAuthTokenHeader())') + and: + SyntaxChecker.tryToCompileGroovy(blockBuilder.toString()) } @Issue('#149') @@ -1770,9 +1890,12 @@ World.'''""" test.contains('assertThatJson(parsedJson).field("ip").matches("([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])\\\\.([01]?\\\\d\\\\d?|2[0-4]\\\\d|25[0-5])")') test.contains('assertThatJson(parsedJson).field("uuid").matches("[a-z0-9]{8}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{4}-[a-z0-9]{12}")') !test.contains('cursor') + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: - methodBuilder << [{ Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties)}, - { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties)}] + methodBuilderName | methodBuilder + "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } + "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } } @@ -1802,9 +1925,84 @@ World.'''""" def test = blockBuilder.toString() then: test.contains('application/vnd\\\\.fraud\\\\.v1\\\\+json.*') + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) where: - methodBuilder << [{ Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties)}, - { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties)}] + methodBuilderName | methodBuilder + "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } + "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } + } + + @Issue('#173') + @Unroll + def "should resolve Optional object when used in query parameters"() { + given: + Contract contractDsl = Contract.make { + request { + method 'GET' + urlPath('/blacklist') { + queryParameters { + parameter 'isActive': value(consumer(optional(regex('(true|false)')))) + parameter 'limit': value(consumer(optional(regex('([0-9]{1,10})')))) + parameter 'offset': value(consumer(optional(regex('([0-9]{1,10})')))) + } + } + headers { + header 'Content-Type': 'application/json' + } + } + response { + status(200) + } + } + MethodBodyBuilder builder = methodBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.appendTo(blockBuilder) + def test = blockBuilder.toString() + then: + !test.contains('org.springframework.cloud.contract.spec.internal.OptionalProperty') + test.contains('(([0-9]{1,10}))?') + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + where: + methodBuilderName | methodBuilder + "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } + "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } + } + + @Issue('#172') + @Unroll + def "should resolve plain text properly via headers"() { + given: + Contract contractDsl = Contract.make { + request { + method 'GET' + url("/foo") + } + response { + status(200) + body '{"a":1}\n{"a":2}' + headers { + contentType(textPlain()) + } + } + } + MethodBodyBuilder builder = methodBuilder(contractDsl) + BlockBuilder blockBuilder = new BlockBuilder(" ") + when: + builder.appendTo(blockBuilder) + def test = blockBuilder.toString() + then: + !test.contains('assertThatJson(parsedJson).field("a").isEqualTo(1)') + test.contains(expectedAssertion) + and: + SyntaxChecker.tryToCompile(methodBuilderName, blockBuilder.toString()) + where: + //order is inverted cause Intellij didn't parse this properly + methodBuilderName | methodBuilder | expectedAssertion + "MockMvcSpockMethodBuilder" | { Contract dsl -> new MockMvcSpockMethodRequestProcessingBodyBuilder(dsl, properties) } | '''responseBody == "{\\"a\\":1}\\n{\\"a\\":2}"''' + "MockMvcJUnitMethodBuilder" | { Contract dsl -> new MockMvcJUnitMethodBodyBuilder(dsl, properties) } | '''assertThat(responseBody).isEqualTo("{\\"a\\":1}\\n{\\"a\\":2}''' } @Issue('#173') diff --git a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy index ab307411d6..54dd921f5c 100755 --- a/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/dsl/WireMockGroovyDslSpec.groovy @@ -48,7 +48,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie created: $(consumer('2014-02-02 12:23:43'), producer(execute('currentDate($it)'))) ) headers { - header 'Content-Type': 'text/plain' + header 'Content-Type': 'application/json' } } } @@ -65,7 +65,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "status" : 200, "body" : "{\\"id\\":\\"123\\",\\"surname\\":\\"Kowalsky\\",\\"name\\":\\"Jan\\",\\"created\\":\\"2014-02-02 12:23:43\\"}", "headers" : { - "Content-Type" : "text/plain" + "Content-Type" : "application/json" } } } @@ -193,7 +193,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie """ ) headers { - header 'Content-Type': 'text/plain' + header 'Content-Type': 'application/json' } } } @@ -210,7 +210,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "status" : 200, "body" : "{\\"created\\":\\"2014-02-02 12:23:43\\",\\"id\\":\\"123\\",\\"name\\":\\"Jan\\",\\"surname\\":\\"Kowalsky\\"}", "headers" : { - "Content-Type" : "text/plain" + "Content-Type" : "application/json" } } } @@ -240,7 +240,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie """ ) headers { - header 'Content-Type': 'text/plain' + header 'Content-Type': 'application/json' } } } @@ -260,7 +260,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "status" : 200, "body" : "{\\"name\\":\\"Jan\\"}", "headers" : { - "Content-Type" : "text/plain" + "Content-Type" : "application/json" } } } @@ -572,7 +572,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie """ ) headers { - header 'Content-Type': 'text/plain' + header 'Content-Type': 'application/json' } } } @@ -592,7 +592,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "status" : 200, "body" : "{\\"name\\":\\"Jan\\"}", "headers" : { - "Content-Type" : "text/plain" + "Content-Type" : "application/json" } } } @@ -1015,7 +1015,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie """ ) headers { - header 'Content-Type': 'text/plain' + header 'Content-Type': 'application/json' } } } @@ -1045,7 +1045,7 @@ class WireMockGroovyDslSpec extends Specification implements WireMockStubVerifie "status" : 200, "body" : "{\\"name\\":\\"Jan\\"}", "headers" : { - "Content-Type" : "text/plain" + "Content-Type" : "application/json" } } } 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 new file mode 100644 index 0000000000..e4f0d39f16 --- /dev/null +++ b/spring-cloud-contract-verifier/src/test/groovy/org/springframework/cloud/contract/verifier/util/SyntaxChecker.groovy @@ -0,0 +1,90 @@ +package org.springframework.cloud.contract.verifier.util + +import groovy.transform.CompileStatic +import org.codehaus.groovy.control.CompilerConfiguration +import org.codehaus.groovy.control.customizers.ImportCustomizer +import org.mdkt.compiler.InMemoryJavaCompiler + +/** + * checking the syntax of produced scripts + */ +@CompileStatic +class SyntaxChecker { + + private static final String[] DEFAULT_IMPORTS = [ + "org.springframework.cloud.contract.spec.Contract", + "com.jayway.restassured.response.ResponseOptions", + "com.jayway.restassured.module.mockmvc.specification.*", + "com.jayway.restassured.module.mockmvc.*", + "org.junit.Test", + "org.junit.Rule", + "com.jayway.jsonpath.DocumentContext", + "com.jayway.jsonpath.JsonPath", + "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", + "javax.ws.rs.client.WebTarget", + "javax.ws.rs.core.Response" + ] + + private static final String DEFAULT_IMPORTS_AS_STRING = DEFAULT_IMPORTS.collect { + "import ${it};" + }.join("\n") + + private static final String STATIC_IMPORTS = [ + "com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.given", + "com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.when", + "com.jayway.restassured.RestAssured.*", + "javax.ws.rs.client.Entity.*", + "org.springframework.cloud.contract.verifier.messaging.util.ContractVerifierMessagingUtil.headers", + "com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson", + "org.assertj.core.api.Assertions.assertThat" + ].collect { "import static ${it};"}.join("\n") + + + public static void tryToCompile(String builderName, String test) { + if (builderName.toLowerCase().contains("spock")) { + tryToCompileGroovy(test) + } else { + tryToCompileJava(test) + } + } + + public static void tryToCompileGroovy(String test) { + def imports = new ImportCustomizer() + CompilerConfiguration configuration = new CompilerConfiguration() + configuration.addCompilationCustomizers(imports) + StringBuffer sourceCode = new StringBuffer() + sourceCode.append("${DEFAULT_IMPORTS_AS_STRING}\n") + sourceCode.append("${STATIC_IMPORTS}\n") + sourceCode.append("\n") + sourceCode.append("WebTarget webTarget") + sourceCode.append("\n") + sourceCode.append(test) + new GroovyShell(SyntaxChecker.classLoader, configuration).parse(sourceCode.toString()) + } + + public static Class tryToCompileJava(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("${STATIC_IMPORTS}\n") + sourceCode.append("\n") + sourceCode.append("public class ${className} {\n") + sourceCode.append("\n") + sourceCode.append(" WebTarget webTarget;") + sourceCode.append("\n") + sourceCode.append(" public void method() {\n") + sourceCode.append(" ${test}\n") + sourceCode.append(" }\n") + sourceCode.append("}") + return InMemoryJavaCompiler.compile(fqnClassName, sourceCode.toString()) + } + +}