Making inProgress not generate a single test method instead of the whole test class
fixes gh-1260
This commit is contained in:
3
.gitignore
vendored
3
.gitignore
vendored
@@ -42,4 +42,5 @@ interpolated-settings.xml
|
||||
interpolated-pom.xml
|
||||
dependency-reduced-pom.xml
|
||||
|
||||
.vscode/
|
||||
.vscode/
|
||||
.flattened-pom.xml
|
||||
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* 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 InProgressContractMethodPreProcessor implements MethodPreProcessor {
|
||||
|
||||
@Override
|
||||
public boolean shouldContinue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accept(SingleContractMetadata metadata) {
|
||||
return metadata.isInProgress();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
interface MethodPreProcessor extends MethodVisitor<MethodPreProcessor> {
|
||||
|
||||
@Override
|
||||
default MethodVisitor<MethodPreProcessor> apply(
|
||||
SingleContractMetadata singleContractMetadata) {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {@code true} if method should be processed
|
||||
*/
|
||||
default boolean shouldContinue() {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -22,6 +22,9 @@ import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
|
||||
import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
|
||||
/**
|
||||
@@ -33,10 +36,14 @@ import org.springframework.cloud.contract.verifier.file.SingleContractMetadata;
|
||||
*/
|
||||
class SingleMethodBuilder {
|
||||
|
||||
private static final Log log = LogFactory.getLog(SingleMethodBuilder.class);
|
||||
|
||||
private List<MethodAnnotations> methodAnnotations = new LinkedList<>();
|
||||
|
||||
private List<MethodMetadata> methodMetadata = new LinkedList<>();
|
||||
|
||||
private List<MethodPreProcessor> methodPreProcessors = new LinkedList<>();
|
||||
|
||||
private List<MethodPostProcessor> methodPostProcessors = new LinkedList<>();
|
||||
|
||||
private List<Given> givens = new LinkedList<>();
|
||||
@@ -86,6 +93,7 @@ class SingleMethodBuilder {
|
||||
SingleMethodBuilder restAssured() {
|
||||
return given(
|
||||
new JavaRestAssuredGiven(this.blockBuilder, this.generatedClassMetaData))
|
||||
.methodPreProcessor(new InProgressContractMethodPreProcessor())
|
||||
.given(new SpockRestAssuredGiven(this.blockBuilder,
|
||||
this.generatedClassMetaData))
|
||||
.when(new JavaRestAssuredWhen(this.blockBuilder,
|
||||
@@ -101,7 +109,8 @@ class SingleMethodBuilder {
|
||||
}
|
||||
|
||||
SingleMethodBuilder jaxRs() {
|
||||
return given(new JaxRsGiven(this.generatedClassMetaData))
|
||||
return methodPreProcessor(new InProgressContractMethodPreProcessor())
|
||||
.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))
|
||||
@@ -112,7 +121,8 @@ class SingleMethodBuilder {
|
||||
|
||||
SingleMethodBuilder messaging() {
|
||||
// @formatter:off
|
||||
return given(new JavaMessagingGiven(this.blockBuilder, this.generatedClassMetaData))
|
||||
return methodPreProcessor(new InProgressContractMethodPreProcessor())
|
||||
.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,
|
||||
@@ -140,6 +150,11 @@ class SingleMethodBuilder {
|
||||
return this;
|
||||
}
|
||||
|
||||
SingleMethodBuilder methodPreProcessor(MethodPreProcessor methodPreProcessor) {
|
||||
this.methodPreProcessors.add(methodPreProcessor);
|
||||
return this;
|
||||
}
|
||||
|
||||
SingleMethodBuilder methodPostProcessor(MethodPostProcessor methodPostProcessor) {
|
||||
this.methodPostProcessors.add(methodPostProcessor);
|
||||
return this;
|
||||
@@ -154,6 +169,14 @@ class SingleMethodBuilder {
|
||||
// \n
|
||||
this.blockBuilder.addEmptyLine();
|
||||
this.generatedClassMetaData.toSingleContractMetadata().forEach(metaData -> {
|
||||
boolean stopProcessing = shouldStopProcessing(metaData);
|
||||
if (stopProcessing) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("The method for meta data [" + metaData
|
||||
+ "] will not be processed further. At least one method pre-processor declared that this method should be skipped.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
// @Test
|
||||
if (visit(this.methodAnnotations, metaData, false)) {
|
||||
this.blockBuilder.addEmptyLine();
|
||||
@@ -187,6 +210,14 @@ class SingleMethodBuilder {
|
||||
return this.blockBuilder;
|
||||
}
|
||||
|
||||
private boolean shouldStopProcessing(SingleContractMetadata metaData) {
|
||||
List<MethodPreProcessor> matchingPreProcessors = this.methodPreProcessors.stream()
|
||||
.filter(m -> m.accept(metaData))
|
||||
.collect(Collectors.toCollection(LinkedList::new));
|
||||
matchingPreProcessors.forEach(m -> m.apply(metaData));
|
||||
return matchingPreProcessors.stream().anyMatch(m -> !m.shouldContinue());
|
||||
}
|
||||
|
||||
private MethodMetadata pickMetadatum() {
|
||||
return this.methodMetadata.stream().filter(Acceptor::accept).findFirst()
|
||||
.orElseThrow(() -> new IllegalStateException(
|
||||
|
||||
@@ -181,6 +181,10 @@ class SingleContractMetadata {
|
||||
return this.http
|
||||
}
|
||||
|
||||
boolean isInProgress() {
|
||||
return this.contract.isInProgress()
|
||||
}
|
||||
|
||||
boolean isMessaging() {
|
||||
return !isHttp()
|
||||
}
|
||||
|
||||
@@ -219,6 +219,10 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock
|
||||
}
|
||||
|
||||
private String singleTestGenerator(Contract contractDsl) {
|
||||
return singleTestGenerator([contractDsl])
|
||||
}
|
||||
|
||||
private String singleTestGenerator(Collection<Contract> contractDsls) {
|
||||
return new JavaTestGenerator() {
|
||||
@Override
|
||||
ClassBodyBuilder classBodyBuilder(BlockBuilder builder, GeneratedClassMetaData metaData, SingleMethodBuilder methodBuilder) {
|
||||
@@ -235,15 +239,15 @@ class SpringTestMethodBodyBuildersSpec extends Specification implements WireMock
|
||||
}
|
||||
})
|
||||
}
|
||||
}.buildClass(properties, [contractMetadata(contractDsl)], "foo", generatedClassData)
|
||||
}.buildClass(properties, [contractMetadata(contractDsls)], "foo", generatedClassData)
|
||||
}
|
||||
|
||||
private GeneratedClassMetaData generatedClassMetaData(Contract contractDsl) {
|
||||
new GeneratedClassMetaData(properties, [contractMetadata(contractDsl)], "foo", generatedClassData)
|
||||
new GeneratedClassMetaData(properties, [contractMetadata([contractDsl])], "foo", generatedClassData)
|
||||
}
|
||||
|
||||
ContractMetadata contractMetadata(Contract contractDsl) {
|
||||
return new ContractMetadata(new File(".").toPath(), false, 0, null, contractDsl)
|
||||
ContractMetadata contractMetadata(Collection<Contract> contractDsls) {
|
||||
return new ContractMetadata(new File(".").toPath(), false, 0, null, contractDsls)
|
||||
}
|
||||
|
||||
@Issue('#187')
|
||||
@@ -3054,4 +3058,76 @@ DocumentContext parsedJson = JsonPath.parse(json);
|
||||
}
|
||||
"webclient" | { properties.testMode = TestMode.WEBTESTCLIENT }
|
||||
}
|
||||
|
||||
@Issue('#1260')
|
||||
def 'should generate test methods for not in progress contracts [#methodBuilderName]'() {
|
||||
given:
|
||||
List<Contract> contractDsl = [
|
||||
Contract.make {
|
||||
name("httpContractNotInProgress")
|
||||
request {
|
||||
method PUT()
|
||||
url '/httpContractNotInProgress'
|
||||
}
|
||||
response {
|
||||
status OK()
|
||||
}
|
||||
},
|
||||
Contract.make {
|
||||
name("httpContractInProgress")
|
||||
inProgress()
|
||||
request {
|
||||
method PUT()
|
||||
url '/httpContractInProgress'
|
||||
}
|
||||
response {
|
||||
status OK()
|
||||
}
|
||||
},
|
||||
Contract.make {
|
||||
name("messagingContractNotInProgress")
|
||||
input {
|
||||
triggeredBy("toString()")
|
||||
}
|
||||
outputMessage {
|
||||
sentTo("messagingContractNotInProgress")
|
||||
body([type: "messagingContractNotInProgress"])
|
||||
}
|
||||
},
|
||||
Contract.make {
|
||||
name("messagingContractInProgress")
|
||||
inProgress()
|
||||
input {
|
||||
triggeredBy("toString()")
|
||||
}
|
||||
outputMessage {
|
||||
sentTo("messagingContractNotInProgress")
|
||||
body([type: "messagingContractNotInProgress"])
|
||||
}
|
||||
}
|
||||
]
|
||||
methodBuilder()
|
||||
when:
|
||||
String test = singleTestGenerator(contractDsl)
|
||||
then:
|
||||
SyntaxChecker.tryToCompile(methodBuilderName, test)
|
||||
and:
|
||||
test.contains('''httpContractNotInProgress''')
|
||||
test.contains('''messagingContractNotInProgress''')
|
||||
and:
|
||||
!test.contains('''httpContractInProgress''')
|
||||
!test.contains('''messagingContractInProgress''')
|
||||
where:
|
||||
methodBuilderName | methodBuilder
|
||||
"spock" | { properties.testFramework = TestFramework.SPOCK }
|
||||
"testng" | { properties.testFramework = TestFramework.TESTNG }
|
||||
"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 }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user