Bumped up version and polished

This commit is contained in:
Marcin Grzejszczak
2016-12-06 23:06:39 +01:00
committed by Marcin Grzejszczak
parent 96525b2ad5
commit d69670db68
22 changed files with 310 additions and 71 deletions

View File

@@ -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

View File

@@ -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.

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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)

View File

@@ -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[]
'''

View File

@@ -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

View File

@@ -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

View File

@@ -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
}
}

View File

@@ -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") }

View File

@@ -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"

View File

@@ -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"() {

View File

@@ -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");
}
}

View File

@@ -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>

View File

@@ -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
}
}
]

View File

@@ -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}"