Bumped up version and polished
This commit is contained in:
committed by
Marcin Grzejszczak
parent
96525b2ad5
commit
d69670db68
@@ -9,6 +9,8 @@ Contract DSL is written in Groovy, but don't be alarmed if you didn't use Groovy
|
||||
a tiny subset of it (namely literals, method calls and closures). What's more the DSL is designed to be programmer-readable without any knowledge of the DSL itself -
|
||||
it's statically typed.
|
||||
|
||||
TIP: Spring Cloud Contract supports defining multiple contracts in a single file!
|
||||
|
||||
The Contract is present in the `spring-cloud-contract-spec` module of the Spring Cloud Contract Verifier repository.
|
||||
|
||||
Let's look at full example of a contract definition.
|
||||
@@ -26,8 +28,6 @@ Not all features of the DSL are used in example above. If you didn't find what y
|
||||
|
||||
WARNING: Spring Cloud Contract Verifier doesn't support XML properly. Please use JSON or help us implement this feature.
|
||||
|
||||
WARNING: Spring Cloud Contract Verifier supports equality check on text response. Regular expressions are not yet available.
|
||||
|
||||
WARNING: The support for the verification of size of JSON arrays is experimental. If you want to turn it on please provide
|
||||
the value of a system property `spring.cloud.contract.verifier.assert.size` equal to `true`. By default this feature is set to
|
||||
`false`. You can also provide the `assertJsonSize` property in the plugin configuration.
|
||||
@@ -47,6 +47,16 @@ You can add a `description` to your contract that is nothing else but an arbitra
|
||||
include::{contract_spec_path}/src/test/groovy/org/springframework/cloud/contract/spec/internal/ContractSpec.groovy[tags=description,indent=0]
|
||||
----
|
||||
|
||||
===== Name
|
||||
|
||||
You can provide a name of your contract. Let's assume that you've provided a name `should register a user`.
|
||||
If you do this then the name of the autogenerated test will be equal to `validate_should_register_a_user`.
|
||||
Also the name of the stub will be `should_register_a_user.json` in case of a WireMock stub.
|
||||
|
||||
IMPORTANT: Please ensure that the name doesn't contain any characters that will make the generated test
|
||||
not possible to compile. Also remember that if you provide the same name for multiple contracts then your
|
||||
autogenerated tests will fail to compile and your generated stubs will override each other.
|
||||
|
||||
===== Ignoring contracts
|
||||
|
||||
If you want to ignore a contract you can either set a value of ignored contracts in the plugin configuration
|
||||
@@ -111,8 +121,6 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
|
||||
//include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/ContractHttpDocsSpec.groovy[tags=bodyAsXml,indent=0]
|
||||
//----
|
||||
|
||||
|
||||
|
||||
==== Response
|
||||
|
||||
Minimal response must contain **HTTP status code**.
|
||||
@@ -216,12 +224,13 @@ include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract
|
||||
|
||||
and the following stub:
|
||||
|
||||
[source,javascript,indent=0]
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
include::{plugins_path}/spring-cloud-contract-converters/src/test/groovy/org/springframework/cloud/contract/verifier/wiremock/DslToWireMockClientConverterSpec.groovy[tags=wiremock,indent=0]
|
||||
----
|
||||
|
||||
==== Executing custom methods on server side
|
||||
|
||||
It is also possible to define a method call to be executed on the server side during the test. Such a method can be added to the class defined as "baseClassForTests"
|
||||
in the configuration. Please see the examples below:
|
||||
|
||||
@@ -240,7 +249,8 @@ include::{plugins_path}/spring-cloud-contract-gradle-plugin/src/test/resources/f
|
||||
----
|
||||
|
||||
==== JAX-RS support
|
||||
Starting with release 0.8.0 we support JAX-RS 2 Client API. Base class needs to define `protected WebTarget webTarget` and server initialization, right now the only option how to test JAX-RS API is to start a web server.
|
||||
|
||||
We support JAX-RS 2 Client API. Base class needs to define `protected WebTarget webTarget` and server initialization, right now the only option how to test JAX-RS API is to start a web server.
|
||||
|
||||
Request with a body needs to have a content type set otherwise `application/octet-stream` is going to be used.
|
||||
|
||||
@@ -268,7 +278,7 @@ section a `async()` method. Example:
|
||||
----
|
||||
org.springframework.cloud.contract.spec.Contract.make {
|
||||
request {
|
||||
method 'GET'
|
||||
method GET()
|
||||
url '/get'
|
||||
}
|
||||
response {
|
||||
@@ -319,7 +329,86 @@ as presented below (note you can use either `$` or `value` methods to provide `c
|
||||
include::{verifier_core_path}/src/test/groovy/org/springframework/cloud/contract/verifier/builder/MessagingMethodBodyBuilderSpec.groovy[tags=consumer_producer]
|
||||
----
|
||||
|
||||
=== Cutomization
|
||||
==== Multiple contracts in one file
|
||||
|
||||
It's possible to define multiple contracts in one file. An example of such a contract can look like this
|
||||
|
||||
[source,groovy,indent=0]
|
||||
----
|
||||
include::{plugins_path}/spring-cloud-contract-maven-plugin/src/test/projects/multiple-contracts/src/test/resources/contracts/com/hello/v1/WithList.groovy[lines=18..-1,indent=0]
|
||||
----
|
||||
|
||||
In this example one contract has the `name` field and the other doesn't. This will lead to generation of
|
||||
two tests that will look more or less like this:
|
||||
|
||||
[source,java,indent=0]
|
||||
----
|
||||
package org.springframework.cloud.contract.verifier.tests.com.hello;
|
||||
|
||||
import com.example.TestBase;
|
||||
import com.jayway.jsonpath.DocumentContext;
|
||||
import com.jayway.jsonpath.JsonPath;
|
||||
import com.jayway.restassured.module.mockmvc.specification.MockMvcRequestSpecification;
|
||||
import com.jayway.restassured.response.ResponseOptions;
|
||||
import org.junit.Test;
|
||||
|
||||
import static com.jayway.restassured.module.mockmvc.RestAssuredMockMvc.*;
|
||||
import static com.toomuchcoding.jsonassert.JsonAssertion.assertThatJson;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
|
||||
public class V1Test extends TestBase {
|
||||
|
||||
@Test
|
||||
public void validate_should_post_a_user() throws Exception {
|
||||
// given:
|
||||
MockMvcRequestSpecification request = given();
|
||||
|
||||
// when:
|
||||
ResponseOptions response = given().spec(request)
|
||||
.post("/users/1");
|
||||
|
||||
// then:
|
||||
assertThat(response.statusCode()).isEqualTo(200);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void validate_withList_1() throws Exception {
|
||||
// given:
|
||||
MockMvcRequestSpecification request = given();
|
||||
|
||||
// when:
|
||||
ResponseOptions response = given().spec(request)
|
||||
.post("/users/2");
|
||||
|
||||
// then:
|
||||
assertThat(response.statusCode()).isEqualTo(200);
|
||||
}
|
||||
|
||||
}
|
||||
----
|
||||
|
||||
Notice that for the contract that has the `name` field the generated test method is named
|
||||
`validate_should_post_a_user`. For the one that doesn't have the name it's called
|
||||
`validate_withList_1`. It corresponds to the name of the file `WithList.groovy` and the
|
||||
index of the contract in the list.
|
||||
|
||||
The generated stubs will look like this
|
||||
|
||||
[source]
|
||||
----
|
||||
should post a user.json
|
||||
1_WithList.json
|
||||
----
|
||||
|
||||
As you can see the first file got the `name` parameter from the contract. The second
|
||||
got the name of the contract file `WithList.groovy` prefixed with the index (in this case
|
||||
contract had index `1` in the list of contracts in the file).
|
||||
|
||||
TIP: As you can see it's much better if you name your contracts since then your tests
|
||||
are far more meaningful.
|
||||
|
||||
|
||||
=== Customization
|
||||
|
||||
==== Extending the DSL
|
||||
|
||||
|
||||
@@ -138,7 +138,7 @@ contracts {
|
||||
contractsWorkOffline = false
|
||||
}
|
||||
|
||||
tasks.create(type: Jar, name: 'verifierStubsJar', dependsOn: 'generateWireMockClientStubs') {
|
||||
tasks.create(type: Jar, name: 'verifierStubsJar', dependsOn: 'convert') {
|
||||
baseName = project.name
|
||||
classifier = contracts.stubsSuffix
|
||||
from contractVerifier.stubsOutputDir
|
||||
@@ -265,7 +265,7 @@ In consumer service you need to configure Spring Cloud Contract Verifier plugin
|
||||
|
||||
[source,bash,indent=0]
|
||||
----
|
||||
./gradlew generateWireMockClientStubs
|
||||
./gradlew generateClientStubs
|
||||
----
|
||||
|
||||
Note that `stubsOutputDir` option has to be set for stub generation to work.
|
||||
|
||||
@@ -43,7 +43,7 @@ interface SingleFileConverter {
|
||||
* Returns the collection of converted contracts into stubs. One contract can
|
||||
* result in multiple stubs.
|
||||
*/
|
||||
Collection<String> convertContents(String rootName, ContractMetadata content)
|
||||
Map<Contract, String> convertContents(String rootName, ContractMetadata content)
|
||||
|
||||
/**
|
||||
* Returns the name of the converted stub file. If you have multiple contracts
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.springframework.cloud.contract.verifier.file.ContractMetadata
|
||||
import org.springframework.cloud.contract.verifier.util.NamesUtil
|
||||
|
||||
import java.nio.charset.StandardCharsets
|
||||
|
||||
/**
|
||||
* Converts DSLs to WireMock stubs
|
||||
*
|
||||
@@ -44,15 +43,19 @@ class DslToWireMockClientConverter extends DslToWireMockConverter {
|
||||
}
|
||||
|
||||
@Override
|
||||
Collection<String> convertContents(String rootName, ContractMetadata contract) {
|
||||
if (contract.convertedContract.size() == 1) {
|
||||
return [convertASingleContract(rootName, contract, contract.convertedContract.first())]
|
||||
Map<Contract, String> convertContents(String rootName, ContractMetadata contract) {
|
||||
if (!(contract.convertedContract.any { it.request })) {
|
||||
return [:]
|
||||
}
|
||||
List<String> convertedContracts = []
|
||||
contract.convertedContract.eachWithIndex { Contract dsl, int index ->
|
||||
if (contract.convertedContract.size() == 1) {
|
||||
return [(contract.convertedContract.first()): convertASingleContract(rootName, contract, contract.convertedContract.first())]
|
||||
}
|
||||
Map<Contract, String> convertedContracts = [:]
|
||||
contract.convertedContract.findAll { it.request }.eachWithIndex { Contract dsl, int index ->
|
||||
String name = dsl.name ? NamesUtil.convertIllegalPackageChars(dsl.name) : "${rootName}_${index}"
|
||||
convertedContracts << convertASingleContract(name, contract, dsl)
|
||||
convertedContracts << [(dsl) : convertASingleContract(name, contract, dsl)]
|
||||
}
|
||||
return convertedContracts
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -88,15 +88,17 @@ class RecursiveFilesConverter {
|
||||
return
|
||||
}
|
||||
int contractsSize = contract.convertedContract.size()
|
||||
contract.convertedContract.eachWithIndex { Contract dsl, int index ->
|
||||
String convertedContent = singleFileConverter.convertContent(entry.key.last().toString(), contract)
|
||||
if (!convertedContent) {
|
||||
return
|
||||
}
|
||||
Map<Contract, String> convertedContent = singleFileConverter.convertContents(entry.key.last().toString(), contract)
|
||||
if (!convertedContent) {
|
||||
return
|
||||
}
|
||||
convertedContent.entrySet().eachWithIndex { Map.Entry<Contract, String> content, int index ->
|
||||
Contract dsl = content.key
|
||||
String converted = content.value
|
||||
Path absoluteTargetPath = createAndReturnTargetDirectory(sourceFile)
|
||||
File newJsonFile = createTargetFileWithProperName(singleFileConverter, absoluteTargetPath,
|
||||
sourceFile, contractsSize, index, dsl)
|
||||
newJsonFile.setText(convertedContent, StandardCharsets.UTF_8.toString())
|
||||
newJsonFile.setText(converted, StandardCharsets.UTF_8.toString())
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new ConversionContractVerifierException("Unable to make conversion of ${sourceFile.name}", e)
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.github.tomakehurst.wiremock.stubbing.StubMapping
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import org.skyscreamer.jsonassert.JSONAssert
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
import org.springframework.cloud.contract.verifier.file.ContractMetadata
|
||||
import spock.lang.Issue
|
||||
import spock.lang.Specification
|
||||
@@ -46,7 +47,7 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
}
|
||||
""")
|
||||
when:
|
||||
String json = converter.convertContent("Test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
String json = converter.convertContents("Test", new ContractMetadata(file.toPath(), false, 0, null)).values().first()
|
||||
then:
|
||||
JSONAssert.assertEquals('''
|
||||
{"request":{"method":"PUT","urlPattern":"/[0-9]{2}"},"response":{"status":200}}
|
||||
@@ -75,17 +76,37 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
}
|
||||
''')
|
||||
when:
|
||||
List<String> json = converter.convertContents("Test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
Map<Contract, String> convertedContents = converter.convertContents("Test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
then:
|
||||
json.size() == 2
|
||||
JSONAssert.assertEquals(jsonResponse(1), json.first(), false)
|
||||
JSONAssert.assertEquals(jsonResponse(2), json.last(), false)
|
||||
convertedContents.size() == 2
|
||||
JSONAssert.assertEquals(jsonResponse(1), convertedContents.values().first(), false)
|
||||
JSONAssert.assertEquals(jsonResponse(2), convertedContents.values().last(), false)
|
||||
}
|
||||
|
||||
private String jsonResponse(int index) {
|
||||
return """{"request":{"method":"PUT","url":"/${index}"},"response":{"status":200}}"""
|
||||
}
|
||||
|
||||
def "should not convert if contract is messaging related"() {
|
||||
given:
|
||||
def converter = new DslToWireMockClientConverter()
|
||||
and:
|
||||
File file = tmpFolder.newFile("dsl1_list.groovy")
|
||||
file.write('''
|
||||
(1..2).collect { int index ->
|
||||
org.springframework.cloud.contract.spec.Contract.make {
|
||||
input {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
''')
|
||||
when:
|
||||
Map<Contract, String> convertedContents = converter.convertContents("Test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
then:
|
||||
convertedContents.isEmpty()
|
||||
}
|
||||
|
||||
@Issue("196")
|
||||
def "should creation of delayed stub responses be possible"() {
|
||||
given:
|
||||
@@ -105,7 +126,7 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
}
|
||||
""")
|
||||
when:
|
||||
String json = converter.convertContent("test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
String json = converter.convertContents("test", new ContractMetadata(file.toPath(), false, 0, null)).values().first()
|
||||
then:
|
||||
JSONAssert.assertEquals('''
|
||||
{"request":{
|
||||
@@ -168,7 +189,7 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
}
|
||||
""")
|
||||
when:
|
||||
String json = converter.convertContent("Test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
String json = converter.convertContents("Test", new ContractMetadata(file.toPath(), false, 0, null)).values().first()
|
||||
then:
|
||||
JSONAssert.assertEquals('''
|
||||
{
|
||||
@@ -250,7 +271,7 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
}
|
||||
""")
|
||||
when:
|
||||
String json = converter.convertContent("test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
String json = converter.convertContents("test", new ContractMetadata(file.toPath(), false, 0, null)).values().first()
|
||||
then:
|
||||
JSONAssert.assertEquals('''
|
||||
{"request":{"urlPath":"/foos","method":"GET"},"response":{"body":"[{\\"id\\":\\"123\\"},{\\"id\\":\\"567\\"}]"}}
|
||||
@@ -280,7 +301,7 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
}
|
||||
""")
|
||||
when:
|
||||
String json = converter.convertContent("test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
String json = converter.convertContents("test", new ContractMetadata(file.toPath(), false, 0, null)).values().first()
|
||||
StubMapping.buildFrom(json)
|
||||
then:
|
||||
noExceptionThrown()
|
||||
@@ -320,7 +341,7 @@ class DslToWireMockClientConverterSpec extends Specification {
|
||||
}
|
||||
''')
|
||||
when:
|
||||
String json = converter.convertContent("Test", new ContractMetadata(file.toPath(), false, 0, null))
|
||||
String json = converter.convertContents("Test", new ContractMetadata(file.toPath(), false, 0, null)).values().first()
|
||||
then:
|
||||
JSONAssert.assertEquals( // tag::wiremock[]
|
||||
'''
|
||||
|
||||
@@ -17,19 +17,17 @@
|
||||
package org.springframework.cloud.contract.verifier.wiremock
|
||||
|
||||
import groovy.io.FileType
|
||||
import org.springframework.cloud.contract.verifier.converter.SingleFileConvertersHolder
|
||||
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
import org.junit.Rule
|
||||
import org.junit.rules.TemporaryFolder
|
||||
import org.springframework.cloud.contract.verifier.config.ContractVerifierConfigProperties
|
||||
import org.springframework.cloud.contract.verifier.converter.SingleFileConverter
|
||||
import org.springframework.cloud.contract.verifier.converter.SingleFileConvertersHolder
|
||||
import org.springframework.util.FileSystemUtils
|
||||
|
||||
import spock.lang.Specification
|
||||
|
||||
import java.nio.file.Path
|
||||
import java.nio.file.Paths
|
||||
|
||||
class RecursiveFilesConverterSpec extends Specification {
|
||||
|
||||
private static
|
||||
@@ -49,12 +47,7 @@ class RecursiveFilesConverterSpec extends Specification {
|
||||
properties.stubsOutputDir = tmpFolder.newFolder("target")
|
||||
FileSystemUtils.copyRecursively(originalSourceRootDirectory, properties.contractsDslDir)
|
||||
and:
|
||||
def singleFileConverterStub = Stub(SingleFileConverter)
|
||||
singleFileConverterStub.canHandleFileName(_) >> { String fileName -> fileName.endsWith(".groovy") }
|
||||
singleFileConverterStub.convertContent(_, _) >> { "converted" }
|
||||
singleFileConverterStub.generateOutputFileNameForInput(_) >> { String inputFileName -> inputFileName.replaceAll('.groovy', '.json') }
|
||||
|
||||
RecursiveFilesConverter recursiveFilesConverter = new RecursiveFilesConverter(singleFileConverterStub, properties)
|
||||
RecursiveFilesConverter recursiveFilesConverter = new RecursiveFilesConverter(properties)
|
||||
when:
|
||||
recursiveFilesConverter.processFiles()
|
||||
then:
|
||||
@@ -63,7 +56,7 @@ class RecursiveFilesConverterSpec extends Specification {
|
||||
Set<String> relativizedCreatedFiles = getRelativePathsForFilesInDirectory(createdFiles, properties.stubsOutputDir)
|
||||
EXPECTED_TARGET_FILES == relativizedCreatedFiles
|
||||
and:
|
||||
createdFiles.each { it.text == "converted" }
|
||||
createdFiles.each { assert it.text.contains("uuid") }
|
||||
}
|
||||
|
||||
def "should recursively convert matching files with exlusions"() {
|
||||
@@ -98,7 +91,7 @@ class RecursiveFilesConverterSpec extends Specification {
|
||||
and:
|
||||
def singleFileConverterStub = Stub(SingleFileConverter)
|
||||
singleFileConverterStub.canHandleFileName(_) >> { true }
|
||||
singleFileConverterStub.convertContent(_, _) >> { throw new NullPointerException("Test conversion error") }
|
||||
singleFileConverterStub.convertContents(_, _) >> { throw new NullPointerException("Test conversion error") }
|
||||
singleFileConverterStub.generateOutputFileNameForInput(_) >> { String inputFileName -> "${inputFileName}2" }
|
||||
ContractVerifierConfigProperties properties = new ContractVerifierConfigProperties()
|
||||
properties.contractsDslDir = tmpFolder.root
|
||||
|
||||
@@ -70,7 +70,7 @@ class ContractVerifierExtension {
|
||||
File generatedTestSourcesDir
|
||||
|
||||
/**
|
||||
* Dir where the generated WireMock stubs from Groovy DSL should be placed.
|
||||
* Dir where the generated stubs from Groovy DSL should be placed.
|
||||
* You can then mention them in your packaging task to create jar with stubs
|
||||
*/
|
||||
File stubsOutputDir
|
||||
|
||||
@@ -26,7 +26,8 @@ import org.springframework.cloud.contract.verifier.wiremock.RecursiveFilesConver
|
||||
import static org.springframework.cloud.contract.verifier.plugin.SpringCloudContractVerifierGradlePlugin.COPY_CONTRACTS_TASK_NAME
|
||||
//TODO: Implement as an incremental task: https://gradle.org/docs/current/userguide/custom_tasks.html#incremental_tasks ?
|
||||
/**
|
||||
* Generates WireMock stubs from the contracts
|
||||
* Generates stubs from the contracts. The name is WireMock related but the implementation
|
||||
* can differ
|
||||
*
|
||||
* @since 1.0.0
|
||||
*/
|
||||
@@ -45,7 +46,7 @@ class GenerateWireMockClientStubsFromDslTask extends ConventionTask {
|
||||
Task copyContractsTask = project.getTasksByName(COPY_CONTRACTS_TASK_NAME, false).first()
|
||||
ContractVerifierConfigProperties props = props(copyContractsTask)
|
||||
File contractsDslDir = contractsDslDir(copyContractsTask, props)
|
||||
logger.info("Spring Cloud Contract Verifier Plugin: Invoking DSL to WireMock client stubs conversion")
|
||||
logger.info("Spring Cloud Contract Verifier Plugin: Invoking DSL to client stubs conversion")
|
||||
props.contractsDslDir = contractsDslDir
|
||||
props.includedContracts = ".*"
|
||||
File outMappingsDir = getStubsOutputDir() != null ? new File(getStubsOutputDir(), DEFAULT_MAPPINGS_FOLDER)
|
||||
@@ -71,7 +72,7 @@ class GenerateWireMockClientStubsFromDslTask extends ConventionTask {
|
||||
try {
|
||||
return task.ext.contractsDslDir
|
||||
} catch (Exception e) {
|
||||
project.logger.error("Couldn't retrieve the contractdsl property set by the copy contracts task", e)
|
||||
project.logger.error("Couldn't retrieve the contract dsl property set by the copy contracts task", e)
|
||||
return props.contractsDslDir
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,8 @@ import org.gradle.jvm.tasks.Jar
|
||||
class SpringCloudContractVerifierGradlePlugin implements Plugin<Project> {
|
||||
|
||||
private static final String GENERATE_SERVER_TESTS_TASK_NAME = 'generateContractTests'
|
||||
private static final String DSL_TO_WIREMOCK_CLIENT_TASK_NAME = 'generateWireMockClientStubs'
|
||||
private static final String DEPRECATED_DSL_TO_WIREMOCK_CLIENT_TASK_NAME = 'generateWireMockClientStubs'
|
||||
private static final String DSL_TO_CLIENT_TASK_NAME = 'generateClientStubs'
|
||||
@PackageScope static final String COPY_CONTRACTS_TASK_NAME = 'copyContracts'
|
||||
private static final String VERIFIER_STUBS_JAR_TASK_NAME = 'verifierStubsJar'
|
||||
|
||||
@@ -69,7 +70,8 @@ class SpringCloudContractVerifierGradlePlugin implements Plugin<Project> {
|
||||
Task copyContracts = createAndConfigureCopyContractsTask(stubsJar, downloader, extension)
|
||||
createAndConfigureMavenPublishPlugin(stubsJar)
|
||||
createGenerateTestsTask(extension, copyContracts)
|
||||
createAndConfigureGenerateWireMockClientStubsFromDslTask(extension, copyContracts)
|
||||
Task clientTask = createAndConfigureGenerateClientStubsFromDslTask(extension, copyContracts)
|
||||
createAndConfigureGenerateWireMockClientStubsFromDslTask(extension, clientTask)
|
||||
addProjectDependencies(project)
|
||||
addIdeaTestSources(project, extension)
|
||||
}
|
||||
@@ -89,6 +91,7 @@ class SpringCloudContractVerifierGradlePlugin implements Plugin<Project> {
|
||||
}
|
||||
|
||||
private void addProjectDependencies(Project project) {
|
||||
//TODO: Consider removing this at some point
|
||||
project.dependencies.add("testCompile", "com.github.tomakehurst:wiremock:2.1.7")
|
||||
project.dependencies.add("testCompile", "com.toomuchcoding.jsonassert:jsonassert:0.4.7")
|
||||
project.dependencies.add("testCompile", "org.assertj:assertj-core:2.3.0")
|
||||
@@ -119,10 +122,19 @@ class SpringCloudContractVerifierGradlePlugin implements Plugin<Project> {
|
||||
task.dependsOn copyContracts
|
||||
}
|
||||
|
||||
// TODO: Remove this task at some point
|
||||
private void createAndConfigureGenerateWireMockClientStubsFromDslTask(ContractVerifierExtension extension,
|
||||
Task mainTask) {
|
||||
Task task = project.tasks.create(DEPRECATED_DSL_TO_WIREMOCK_CLIENT_TASK_NAME)
|
||||
task.description = "DEPRECATED: Generate WireMock client stubs from the contracts. Use ${DSL_TO_CLIENT_TASK_NAME} task."
|
||||
task.group = GROUP_NAME
|
||||
task.dependsOn mainTask
|
||||
}
|
||||
|
||||
private Task createAndConfigureGenerateClientStubsFromDslTask(ContractVerifierExtension extension,
|
||||
Task copyContracts) {
|
||||
Task task = project.tasks.create(DSL_TO_WIREMOCK_CLIENT_TASK_NAME, GenerateWireMockClientStubsFromDslTask)
|
||||
task.description = "Generate WireMock client stubs from the contracts"
|
||||
Task task = project.tasks.create(DSL_TO_CLIENT_TASK_NAME, GenerateWireMockClientStubsFromDslTask)
|
||||
task.description = "Generate client stubs from the contracts"
|
||||
task.group = GROUP_NAME
|
||||
task.conventionMapping.with {
|
||||
downloader = { gradleContractsDownloader }
|
||||
@@ -130,6 +142,7 @@ class SpringCloudContractVerifierGradlePlugin implements Plugin<Project> {
|
||||
configProperties = { extension }
|
||||
}
|
||||
task.dependsOn copyContracts
|
||||
return task
|
||||
}
|
||||
|
||||
private Task createAndConfigureStubsJarTasks(ContractVerifierExtension extension) {
|
||||
@@ -139,7 +152,7 @@ class SpringCloudContractVerifierGradlePlugin implements Plugin<Project> {
|
||||
return task
|
||||
} else {
|
||||
task = project.tasks.create(type: Jar, name: VERIFIER_STUBS_JAR_TASK_NAME,
|
||||
dependsOn: DSL_TO_WIREMOCK_CLIENT_TASK_NAME) {
|
||||
dependsOn: DSL_TO_CLIENT_TASK_NAME) {
|
||||
baseName = project.name
|
||||
classifier = extension.stubsSuffix
|
||||
from { extension.stubsOutputDir ?: project.file("${project.buildDir}/stubs") }
|
||||
|
||||
@@ -43,6 +43,7 @@ class BasicFunctionalSpec extends ContractVerifierIntegrationSpec {
|
||||
BuildResult result = run(checkAndPublishToMavenLocal())
|
||||
then:
|
||||
result.task(":generateWireMockClientStubs").outcome == SUCCESS
|
||||
result.task(":generateClientStubs").outcome == SUCCESS
|
||||
result.task(":generateContractTests").outcome == SUCCESS
|
||||
|
||||
and: "tests generated"
|
||||
|
||||
@@ -55,7 +55,7 @@ class ContractVerifierSpec extends Specification {
|
||||
project.plugins.apply(SpringCloudContractVerifierGradlePlugin)
|
||||
|
||||
expect:
|
||||
project.tasks.findByName("generateWireMockClientStubs") != null
|
||||
project.tasks.findByName("generateClientStubs") != null
|
||||
}
|
||||
|
||||
def "should create verifierStubsJar task"() {
|
||||
@@ -71,7 +71,7 @@ class ContractVerifierSpec extends Specification {
|
||||
project.plugins.apply(SpringCloudContractVerifierGradlePlugin)
|
||||
|
||||
expect:
|
||||
project.tasks.verifierStubsJar.getDependsOn().contains("generateWireMockClientStubs")
|
||||
project.tasks.verifierStubsJar.getDependsOn().contains("generateClientStubs")
|
||||
}
|
||||
|
||||
def "should create copyContracts task"() {
|
||||
|
||||
@@ -1 +1 @@
|
||||
server.port=8085
|
||||
server.port=0
|
||||
@@ -1 +1 @@
|
||||
server.port=8094
|
||||
server.port=0
|
||||
@@ -1 +1 @@
|
||||
server.port=8085
|
||||
server.port=0
|
||||
@@ -1 +1 @@
|
||||
server.port=8091
|
||||
server.port=0
|
||||
@@ -1 +1 @@
|
||||
server.port=8085
|
||||
server.port=0
|
||||
@@ -1 +1 @@
|
||||
server.port=8092
|
||||
server.port=0
|
||||
@@ -16,6 +16,11 @@
|
||||
*/
|
||||
package org.springframework.cloud.contract.maven.verifier;
|
||||
|
||||
import static io.takari.maven.testing.TestMavenRuntime.newParameter;
|
||||
import static io.takari.maven.testing.TestResources.assertFilesNotPresent;
|
||||
import static io.takari.maven.testing.TestResources.assertFilesPresent;
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
@@ -25,11 +30,6 @@ import org.junit.Test;
|
||||
import io.takari.maven.testing.TestMavenRuntime;
|
||||
import io.takari.maven.testing.TestResources;
|
||||
|
||||
import static io.takari.maven.testing.TestMavenRuntime.newParameter;
|
||||
import static io.takari.maven.testing.TestResources.assertFilesNotPresent;
|
||||
import static io.takari.maven.testing.TestResources.assertFilesPresent;
|
||||
import static org.assertj.core.api.BDDAssertions.then;
|
||||
|
||||
public class PluginUnitTest {
|
||||
|
||||
@Rule
|
||||
@@ -213,4 +213,34 @@ public class PluginUnitTest {
|
||||
File test = new File(basedir, path);
|
||||
then(FileUtils.readFileToString(test)).contains("extends TestBase").contains("import com.example.TestBase");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGenerateContractTestsWithAFileContainingAListOfContracts() throws Exception {
|
||||
File basedir = this.resources.getBasedir("multiple-contracts");
|
||||
|
||||
this.maven.executeMojo(basedir, "generateTests", newParameter("testFramework", "JUNIT"));
|
||||
|
||||
String path = "target/generated-test-sources/contracts/org/springframework/cloud/contract/verifier/tests/com/hello/V1Test.java";
|
||||
assertFilesPresent(basedir, path);
|
||||
File test = new File(basedir, path);
|
||||
then(FileUtils.readFileToString(test))
|
||||
.contains("public void validate_should_post_a_user() throws Exception {")
|
||||
.contains("public void validate_withList_1() throws Exception {");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void shouldGenerateStubsWithAFileContainingAListOfContracts() throws Exception {
|
||||
File basedir = this.resources.getBasedir("multiple-contracts");
|
||||
|
||||
this.maven.executeMojo(basedir, "convert", newParameter("stubsDirectory", "target/foo"));
|
||||
|
||||
String firstFile = "target/foo/mappings/com/hello/v1/should post a user.json";
|
||||
File test = new File(basedir, firstFile);
|
||||
assertFilesPresent(basedir, "target/foo/mappings/com/hello/v1/1_WithList.json");
|
||||
then(FileUtils.readFileToString(test)).contains("/users/1");
|
||||
String secondFile = "target/foo/mappings/com/hello/v1/1_WithList.json";
|
||||
File test2 = new File(basedir, secondFile);
|
||||
assertFilesPresent(basedir, "target/foo/mappings/com/hello/v1/should post a user.json");
|
||||
then(FileUtils.readFileToString(test2)).contains("/users/2");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
|
||||
Copyright 2013-2016 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
|
||||
|
||||
http://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.
|
||||
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<groupId>org.springframework.cloud.verifier.sample</groupId>
|
||||
<artifactId>sample-project</artifactId>
|
||||
<version>0.1</version>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.springframework.cloud</groupId>
|
||||
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<baseClassForTests>com.example.FooBase</baseClassForTests>
|
||||
<baseClassMappings>
|
||||
<baseClassMapping>
|
||||
<contractPackageRegex>.*com.*</contractPackageRegex>
|
||||
<baseClassFQN>com.example.TestBase</baseClassFQN>
|
||||
</baseClassMapping >
|
||||
</baseClassMappings>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
</project>
|
||||
@@ -0,0 +1,40 @@
|
||||
/**
|
||||
*
|
||||
* Copyright 2013-2016 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
|
||||
*
|
||||
* http://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.
|
||||
*/
|
||||
|
||||
import org.springframework.cloud.contract.spec.Contract
|
||||
|
||||
[
|
||||
Contract.make {
|
||||
name("should post a user")
|
||||
request {
|
||||
method 'POST'
|
||||
url('/users/1')
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
}
|
||||
},
|
||||
Contract.make {
|
||||
request {
|
||||
method 'POST'
|
||||
url('/users/2')
|
||||
}
|
||||
response {
|
||||
status 200
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -63,7 +63,7 @@ class MethodBuilder {
|
||||
|
||||
private static String methodName(ContractMetadata contract, File stubsFile, Contract stubContent) {
|
||||
if (stubContent.name) {
|
||||
return NamesUtil.camelCase(stubContent.name)
|
||||
return NamesUtil.camelCase(NamesUtil.convertIllegalPackageChars(stubContent.name))
|
||||
} else if (contract.convertedContract.size() > 1) {
|
||||
int index = contract.convertedContract.findIndexOf { it == stubContent}
|
||||
return "${camelCasedMethodFromFileName(stubsFile)}_${index}"
|
||||
|
||||
Reference in New Issue
Block a user