diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/builder/RestAssuredGiven.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/builder/RestAssuredGiven.java index 2caa8e0c79..84e15323ba 100644 --- a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/builder/RestAssuredGiven.java +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/builder/RestAssuredGiven.java @@ -43,7 +43,9 @@ class RestAssuredGiven implements Given, BodyMethodVisitor, RestAssuredAcceptor .addAll(Arrays.asList(new MockMvcHeadersGiven(blockBuilder), new MockMvcCookiesGiven(blockBuilder), new MockMvcBodyGiven(blockBuilder, generatedClassMetaData, bodyParser), new JavaMultipartGiven(blockBuilder, generatedClassMetaData, bodyParser), - new SpockMockMvcMultipartGiven(blockBuilder, generatedClassMetaData, bodyParser))); + new SpockMockMvcMultipartGiven(blockBuilder, generatedClassMetaData, bodyParser), + new SpockExplicitMultipartGiven(blockBuilder, generatedClassMetaData, bodyParser), + new SpockWebTestClientMultipartGiven(blockBuilder, generatedClassMetaData, bodyParser))); } @Override diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/builder/SpockExplicitMultipartGiven.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/builder/SpockExplicitMultipartGiven.java new file mode 100644 index 0000000000..ba341ed66c --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/builder/SpockExplicitMultipartGiven.java @@ -0,0 +1,68 @@ +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; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +class SpockExplicitMultipartGiven implements Given, ExplicitAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final BodyReader bodyReader; + + private final BodyParser bodyParser; + + SpockExplicitMultipartGiven(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(MapConverter.getTestSideValuesForNonBody(parameter.getValue())) + ")"; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Request request = metadata.getContract().getRequest(); + return request != null && request.getMultipart() != null && acceptType(this.generatedClassMetaData) + && this.generatedClassMetaData.configProperties.getTestFramework() == TestFramework.SPOCK; + } + +} diff --git a/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/builder/SpockWebTestClientMultipartGiven.java b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/builder/SpockWebTestClientMultipartGiven.java new file mode 100644 index 0000000000..c7f754bcc2 --- /dev/null +++ b/spring-cloud-contract-verifier/src/main/java/org/springframework/cloud/contract/verifier/builder/SpockWebTestClientMultipartGiven.java @@ -0,0 +1,68 @@ +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; +import org.springframework.cloud.contract.verifier.util.MapConverter; + +public class SpockWebTestClientMultipartGiven implements Given, WebTestClientAcceptor { + + private final BlockBuilder blockBuilder; + + private final GeneratedClassMetaData generatedClassMetaData; + + private final BodyReader bodyReader; + + private final BodyParser bodyParser; + + SpockWebTestClientMultipartGiven(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(MapConverter.getTestSideValuesForNonBody(parameter.getValue())) + ")"; + } + + @Override + public boolean accept(SingleContractMetadata metadata) { + Request request = metadata.getContract().getRequest(); + return request != null && request.getMultipart() != null && acceptType(this.generatedClassMetaData) + && this.generatedClassMetaData.configProperties.getTestFramework() == TestFramework.SPOCK; + } + +} 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 bd1a525f12..4f8ef0e798 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 @@ -1659,7 +1659,7 @@ World.'''""" } - @Issue('180') + @Issue(['180', '1667']) def 'should generate proper test code when having multipart parameters with named as map with #methodBuilderName'() { given: org.springframework.cloud.contract.spec.Contract contractDsl = org.springframework.cloud.contract.spec.Contract.make { @@ -1699,6 +1699,15 @@ World.'''""" "testng" | { configProperties.testFramework = TestFramework.TESTNG } "mockmvc" | { configProperties.testMode = TestMode.MOCKMVC } "webclient" | { configProperties.testMode = TestMode.WEBTESTCLIENT } + "spock-mockmvc" | { + configProperties.testFramework = TestFramework.SPOCK; configProperties.testMode = TestMode.MOCKMVC + } + "spock-explicit" | { + configProperties.testFramework = TestFramework.SPOCK; configProperties.testMode = TestMode.EXPLICIT + } + "spock-webclient" | { + configProperties.testFramework = TestFramework.SPOCK; configProperties.testMode = TestMode.WEBTESTCLIENT + } } @Issue('#216')