Merge pull request #1184 from shanman190/bugfix/extension-dsl

Bugfix/extension dsl
This commit is contained in:
Marcin Grzejszczak
2019-09-03 21:07:50 +02:00
committed by GitHub
78 changed files with 1140 additions and 2426 deletions

View File

@@ -7,9 +7,7 @@ buildscript {
jcenter()
}
//For plugin-publish-plugin. Could be limited only to that dependency with Gradle 5.1+ - https://docs.gradle.org/5.1.1/release-notes.html#repository-to-dependency-matching
maven {
url 'https://plugins.gradle.org/m2/'
}
gradlePluginPortal()
}
dependencies {
classpath "com.bmuschko:gradle-nexus-plugin:2.3"
@@ -25,9 +23,7 @@ ext {
repoUser = System.getenv('REPO_USERNAME') ?: project.findProperty('REPO_USERNAME') ?: ''
repoPass = System.getenv('REPO_PASSWORD') ?: project.findProperty('REPO_PASSWORD') ?: ''
contractVerifierGradlePluginLibsDir = "$buildDir/contractVerifier-gradle-plugin-libs"
testSystemProperties = [
'contract-gradle-plugin-libs-dir': contractVerifierGradlePluginLibsDir,
"WORK_OFFLINE" : gradle.startParameter.isOffline() ? 'TRUE' : 'FALSE'
]
JavaVersion javaVer = JavaVersion.current()
@@ -38,10 +34,9 @@ ext {
project.version = findProperty('verifierVersion')
apply plugin: 'groovy'
apply plugin: "java-gradle-plugin"
apply from: "$rootDir/gradle/release.gradle"
apply plugin: 'eclipse'
//apply plugin: "jacoco"
apply plugin: 'checkstyle'
group = 'org.springframework.cloud'
@@ -65,8 +60,6 @@ task allInsight(type: DependencyInsightReportTask) {}
configurations {
// fixing the groovydoc issue https://stackoverflow.com/questions/20618857/gradle-task-groovydoc-failing-with-noclassdeffounderror
jansi.extendsFrom(runtime)
contractVerifierGradlePluginLibs
}
dependencies {
@@ -88,8 +81,6 @@ dependencies {
}
testCompile 'info.solidsoft.spock:spock-global-unroll:0.5.0'
testCompile gradleTestKit()
checkstyle "org.springframework.cloud:spring-cloud-build:${springCloudBuildVersion}"
}
task libtest() {
@@ -121,19 +112,9 @@ groovydoc {
}
dependencies {
contractVerifierGradlePluginLibs project
jansi 'org.fusesource.jansi:jansi:1.11'
}
task archiveContractVerifierGradlePluginLibsDependencies(type: Sync) {
enabled = !incompatibleJdk
from configurations.contractVerifierGradlePluginLibs.resolvedConfiguration.resolvedArtifacts.collect { it.file }
into contractVerifierGradlePluginLibsDir
}
archiveContractVerifierGradlePluginLibsDependencies.dependsOn project.tasks.jar
test.dependsOn archiveContractVerifierGradlePluginLibsDependencies
/*jacoco {
toolVersion = "0.7.7.201606060606"
}

View File

@@ -1,616 +0,0 @@
/*
* 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.plugin
import org.gradle.api.tasks.Internal
import javax.inject.Inject
import groovy.transform.CompileStatic
import org.apache.commons.logging.Log
import org.apache.commons.logging.LogFactory
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.model.ObjectFactory
import org.gradle.api.provider.ListProperty
import org.gradle.api.provider.MapProperty
import org.gradle.api.provider.Property
import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Optional
import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties
import org.springframework.cloud.contract.verifier.config.TestFramework
import org.springframework.cloud.contract.verifier.config.TestMode
/**
* @author Marcin Grzejszczak
* @author Anatoliy Balakirev
*/
@CompileStatic
class ContractVerifierExtension {
private static final Log log = LogFactory.getLog(ContractVerifierExtension)
@Deprecated
void setTargetFramework(TestFramework targetFramework) {
log.warn("Please use the [testFramework] field. This one is deprecated")
this.testFramework.set(targetFramework)
}
@Deprecated
TestFramework getTargetFramework() {
return getTestFramework().get()
}
/**
* For which unit test library tests should be generated
*/
Property<TestFramework> testFramework
/**
* Which mechanism should be used to invoke REST calls during tests
*/
Property<TestMode> testMode
/**
* Base package for generated tests
*/
Property<String> basePackageForTests
/**
* Class which all generated tests should extend
*/
Property<String> baseClassForTests
/**
* Suffix for generated test classes, like Spec or Test
*/
Property<String> nameSuffixForTests
/**
* Rule class that should be added to generated tests
*/
Property<String> ruleClassForTests
/**
* Patterns that should not be taken into account for processing
*/
ListProperty<String> excludedFiles
/**
* Patterns that should be taken into account for processing
*/
ListProperty<String> includedFiles
/**
* Patterns for which generated tests should be @Ignored
*/
ListProperty<String> ignoredFiles
/**
* Imports that should be added to generated tests
*/
ListProperty<String> imports
/**
* Static imports that should be added to generated tests
*/
ListProperty<String> staticImports
/**
* Directory containing contracts written using the GroovyDSL
*/
DirectoryProperty contractsDslDir
/**
* Test source directory where tests generated from Groovy DSL should be placed
*/
DirectoryProperty generatedTestSourcesDir
/**
* Test resource directory where tests generated from Groovy DSL should be referenced
*/
DirectoryProperty generatedTestResourcesDir
/**
* 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
*/
DirectoryProperty stubsOutputDir
/**
* Suffix for the generated Stubs Jar task
*/
Property<String> stubsSuffix
/**
* Incubating feature. You can check the size of JSON arrays. If not turned on
* explicitly will be disabled.
*/
Property<Boolean> assertJsonSize
/**
* When enabled, this flag will tell stub runner to throw an exception when no stubs /
* contracts were found.
*/
Property<Boolean> failOnNoContracts
/**
* If set to true then if any contracts that are in progress are found, will break the
* build. On the producer side you need to be explicit about the fact that you have
* contracts in progress and take into consideration that you might be causing false
* positive test execution results on the consumer side.
*/
Property<Boolean> failOnInProgress
ContractRepository contractRepository
/**
* Dependency that contains packaged contracts
*/
Dependency contractDependency
/**
* The path in the JAR with all the contracts where contracts for this particular service lay.
* If not provided will be resolved to {@code groupid/artifactid}. Example:
* </p>
* If {@code groupid} is {@code com.example} and {@code artifactid} is {@code service} then the resolved path will be
* {@code /com/example/artifactid}
*/
Property<String> contractsPath
/**
* Picks the mode in which stubs will be found and registered
*/
Property<StubRunnerProperties.StubsMode> contractsMode
/**
* A package that contains all the base clases for generated tests. If your contract resides in a location
* {@code src/test/resources/contracts/com/example/v1/} and you provide the {@code packageWithBaseClasses}
* value to {@code com.example.contracts.base} then we will search for a test source file that will
* have the package {@code com.example.contracts.base} and name {@code ExampleV1Base}. As you can see
* it will take the two last folders to and attach {@code Base} to its name.
*/
Property<String> packageWithBaseClasses
/**
* A way to override any base class mappings. The keys are regular expressions on the package name
* and the values FQN to a base class for that given expression.
* </p>
* Example of a mapping
* </p>
* {@code .*.com.example.v1..*} -> {@code com.example.SomeBaseClass}
* </p>
* When a contract's package matches the provided regular expression then extending class will be the one
* provided in the map - in this case {@code com.example.SomeBaseClass}
*/
MapProperty<String, String> baseClassMappings
/**
* If set to true then the {@code target} or {@code build} folders are getting
* excluded from any operations. This is used out of the box when working with
* common repo with contracts.
*/
Property<Boolean> excludeBuildFolders
/**
* If set to {@code true} will not assert whether the downloaded stubs / contract
* JAR was downloaded from a remote location or a local one(only applicable to Maven repos, not Git or Pact)
*
* @deprecated - with 2.1.0 this option is redundant
*/
@Deprecated
Property<Boolean> contractsSnapshotCheckSkip
/**
* If set to {@code false} will NOT delete stubs from a temporary
* folder after running tests
*/
Property<Boolean> deleteStubsAfterTest
/**
* If {@code true} then will convert contracts to a YAML representation
*/
Property<Boolean> convertToYaml
/**
* Map of properties that can be passed to custom {@link org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder}
*/
MapProperty<String, String> contractsProperties
void contractDependency(@DelegatesTo(Dependency) Closure closure) {
closure.delegate = contractDependency
closure.call()
}
void baseClassMappings(@DelegatesTo(BaseClassMapping) Closure closure) {
closure.delegate = new BaseClassMapping(baseClassMappings)
closure.call()
}
void contractRepository(@DelegatesTo(ContractRepository) Closure closure) {
closure.delegate = contractRepository
closure.call()
}
void contractsProperties(Map<String, String> map) {
contractsProperties.set(map)
}
void setContractsProperties(Map<String, String> map) {
contractsProperties.set(map)
}
/**
* Is set to true will not provide the default publication task
*/
Property<Boolean> disableStubPublication
// Added for backward compatibility only. Use setter of dedicated enum type
@Deprecated
void setTestMode(String testMode) {
if (testMode != null) {
this.testMode.set(TestMode.valueOf(testMode.toUpperCase()))
}
}
// Added for backward compatibility only. Use setter of dedicated enum type
@Deprecated
void setTestFramework(String testFramework) {
if (testFramework != null) {
this.testFramework.set(TestFramework.valueOf(testFramework.toUpperCase()))
}
}
// Added for backward compatibility only. Use setter of dedicated enum type
@Deprecated
void setContractsMode(String contractsMode) {
if (contractsMode != null) {
this.contractsMode.set(StubRunnerProperties.StubsMode.valueOf(contractsMode.toUpperCase()))
}
}
void setBasePackageForTests(String basePackageForTests) {
this.basePackageForTests.set(basePackageForTests)
}
void setBaseClassForTests(String baseClassForTests) {
this.baseClassForTests.set(baseClassForTests)
}
void setNameSuffixForTests(String nameSuffixForTests) {
this.nameSuffixForTests.set(nameSuffixForTests)
}
void setRuleClassForTests(String ruleClassForTests) {
this.ruleClassForTests.set(ruleClassForTests)
}
void setContractsDslDir(String contractsDslDir) {
this.contractsDslDir.set(new File(contractsDslDir))
}
void setGeneratedTestSourcesDir(String generatedTestSourcesDir) {
this.generatedTestSourcesDir.set(new File(generatedTestSourcesDir))
}
void setGeneratedTestResourcesDir(String generatedTestResourcesDir) {
this.generatedTestResourcesDir.set(new File(generatedTestResourcesDir))
}
void setStubsOutputDir(String stubsOutputDir) {
this.stubsOutputDir.set(new File(stubsOutputDir))
}
void setStubsSuffix(String stubsSuffix) {
this.stubsSuffix.set(stubsSuffix)
}
void setContractsPath(String contractsPath) {
this.contractsPath.set(contractsPath)
}
void setPackageWithBaseClasses(String packageWithBaseClasses) {
this.packageWithBaseClasses.set(packageWithBaseClasses)
}
void setBasePackageForTests(GString basePackageForTests) {
this.basePackageForTests.set(basePackageForTests.toString())
}
void setBaseClassForTests(GString baseClassForTests) {
this.baseClassForTests.set(baseClassForTests.toString())
}
void setNameSuffixForTests(GString nameSuffixForTests) {
this.nameSuffixForTests.set(nameSuffixForTests.toString())
}
void setRuleClassForTests(GString ruleClassForTests) {
this.ruleClassForTests.set(ruleClassForTests.toString())
}
void setContractsDslDir(GString contractsDslDir) {
this.contractsDslDir.set(new File(contractsDslDir.toString()))
}
void setGeneratedTestSourcesDir(GString generatedTestSourcesDir) {
this.generatedTestSourcesDir.set(new File(generatedTestSourcesDir.toString()))
}
void setGeneratedTestResourcesDir(GString generatedTestResourcesDir) {
this.generatedTestResourcesDir.set(new File(generatedTestResourcesDir.toString()))
}
void setStubsOutputDir(GString stubsOutputDir) {
this.stubsOutputDir.set(new File(stubsOutputDir.toString()))
}
void setStubsSuffix(GString stubsSuffix) {
this.stubsSuffix.set(stubsSuffix.toString())
}
void setContractsPath(GString contractsPath) {
this.contractsPath.set(contractsPath.toString())
}
void setPackageWithBaseClasses(GString packageWithBaseClasses) {
this.packageWithBaseClasses.set(packageWithBaseClasses.toString())
}
@Inject
ContractVerifierExtension(ObjectFactory objects) {
this.testFramework = objects.property(TestFramework).convention(TestFramework.JUNIT)
this.testMode = objects.property(TestMode).convention(TestMode.MOCKMVC)
this.basePackageForTests = objects.property(String)
this.baseClassForTests = objects.property(String)
this.nameSuffixForTests = objects.property(String)
this.ruleClassForTests = objects.property(String)
this.excludedFiles = objects.listProperty(String).convention([])
this.includedFiles = objects.listProperty(String).convention([])
this.ignoredFiles = objects.listProperty(String).convention([])
this.imports = objects.listProperty(String).convention([])
this.staticImports = objects.listProperty(String).convention([])
this.contractsDslDir = objects.directoryProperty()
this.generatedTestSourcesDir = objects.directoryProperty()
this.generatedTestResourcesDir = objects.directoryProperty()
this.stubsOutputDir = objects.directoryProperty()
this.stubsSuffix = objects.property(String).convention("stubs")
this.assertJsonSize = objects.property(Boolean).convention(false)
this.failOnNoContracts = objects.property(Boolean).convention(true)
this.failOnInProgress = objects.property(Boolean).convention(true)
this.contractRepository = new ContractRepository(objects)
this.contractDependency = new Dependency(objects)
this.contractsPath = objects.property(String)
this.contractsMode = objects.property(StubRunnerProperties.StubsMode).convention(StubRunnerProperties.StubsMode.CLASSPATH)
this.packageWithBaseClasses = objects.property(String)
this.baseClassMappings = objects.mapProperty(String, String).convention([:])
this.excludeBuildFolders = objects.property(Boolean).convention(false)
this.contractsSnapshotCheckSkip = objects.property(Boolean).convention(false)
this.deleteStubsAfterTest = objects.property(Boolean).convention(true)
this.convertToYaml = objects.property(Boolean).convention(false)
this.contractsProperties = objects.mapProperty(String, String).convention([:])
this.disableStubPublication = objects.property(Boolean).convention(false)
}
static class Dependency {
@Input
@Optional
Property<String> groupId
@Input
@Optional
Property<String> artifactId
@Input
@Optional
Property<String> version
@Input
@Optional
Property<String> classifier
@Input
@Optional
Property<String> stringNotation
@Inject
Dependency(ObjectFactory objects) {
groupId = objects.property(String)
artifactId = objects.property(String)
version = objects.property(String)
classifier = objects.property(String)
stringNotation = objects.property(String)
}
@Override
String toString() {
return "Dependency{" +
"groupId=" + groupId.getOrNull() +
", artifactId=" + artifactId.getOrNull() +
", classifier=" + classifier.getOrNull() +
", version=" + version.getOrNull() +
", stringNotation=" + stringNotation.getOrNull() +
'}'
}
void setGroupId(String groupId) {
this.groupId.set(groupId)
}
void setArtifactId(String artifactId) {
this.artifactId.set(artifactId)
}
void setVersion(String version) {
this.version.set(version)
}
void setClassifier(String classifier) {
this.classifier.set(classifier)
}
void setStringNotation(String stringNotation) {
this.stringNotation.set(stringNotation)
}
void setGroupId(GString groupId) {
this.groupId.set(groupId.toString())
}
void setArtifactId(GString artifactId) {
this.artifactId.set(artifactId.toString())
}
void setVersion(GString version) {
this.version.set(version.toString())
}
void setClassifier(GString classifier) {
this.classifier.set(classifier.toString())
}
void setStringNotation(GString stringNotation) {
this.stringNotation.set(stringNotation.toString())
}
}
static class BaseClassMapping {
private final MapProperty<String, String> delegate
private BaseClassMapping(MapProperty<String, String> delegate) {
this.delegate = delegate
}
void baseClassMapping(String packageRegex, String fqnBaseClass) {
delegate.put(packageRegex, fqnBaseClass)
}
void baseClassMapping(Map<String, String> mapping) {
delegate.putAll(mapping)
}
}
// This class is used as an input to the tasks, so all fields are marked as `@Input` to allow incremental build
static class ContractRepository {
@Input
@Optional
Property<String> repositoryUrl
@Input
@Optional
Property<String> username
@Input
@Optional
Property<String> password
@Input
@Optional
Property<Integer> proxyPort
@Input
@Optional
Property<String> proxyHost
/**
* Not used any more, as we switched to Gradle's incremental build.
*/
@Internal
@Deprecated
boolean cacheDownloadedContracts
@Inject
ContractRepository(ObjectFactory objects) {
this.repositoryUrl = objects.property(String)
this.username = objects.property(String)
this.password = objects.property(String)
this.proxyHost = objects.property(String)
this.proxyPort = objects.property(Integer)
}
@Override
String toString() {
return "ContractRepository{" +
"repositoryUrl=" + repositoryUrl.getOrNull() +
", username=" + username.getOrNull() +
", password=" + password.getOrNull() +
", proxyPort=" + proxyPort.getOrNull() +
", proxyHost=" + proxyHost.getOrNull() +
'}'
}
void setRepositoryUrl(String repositoryUrl) {
this.repositoryUrl.set(repositoryUrl)
}
void setUsername(String username) {
this.username.set(username)
}
void setPassword(String password) {
this.password.set(password)
}
void setProxyHost(String proxyHost) {
this.proxyHost.set(proxyHost)
}
void setRepositoryUrl(GString repositoryUrl) {
this.repositoryUrl.set(repositoryUrl.toString())
}
void setUsername(GString username) {
this.username.set(username.toString())
}
void setPassword(GString password) {
this.password.set(password.toString())
}
void setProxyHost(GString proxyHost) {
this.proxyHost.set(proxyHost.toString())
}
void setProxyPort(Integer proxyPort) {
this.proxyPort.set(proxyPort)
}
void repositoryUrl(String repositoryUrl) {
this.repositoryUrl.set(repositoryUrl)
}
void username(String username) {
this.username.set(username)
}
void password(String password) {
this.password.set(password)
}
void proxyHost(String proxyHost) {
this.proxyHost.set(proxyHost)
}
void repositoryUrl(GString repositoryUrl) {
this.repositoryUrl.set(repositoryUrl.toString())
}
void username(GString username) {
this.username.set(username.toString())
}
void password(GString password) {
this.password.set(password.toString())
}
void proxyHost(GString proxyHost) {
this.proxyHost.set(proxyHost.toString())
}
}
}

View File

@@ -0,0 +1,791 @@
/*
* 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.plugin;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.gradle.api.Action;
import org.gradle.api.file.DirectoryProperty;
import org.gradle.api.file.ProjectLayout;
import org.gradle.api.model.ObjectFactory;
import org.gradle.api.provider.ListProperty;
import org.gradle.api.provider.MapProperty;
import org.gradle.api.provider.Property;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.Internal;
import org.gradle.api.tasks.Optional;
import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties;
import org.springframework.cloud.contract.verifier.config.TestFramework;
import org.springframework.cloud.contract.verifier.config.TestMode;
import org.springframework.util.Assert;
import javax.inject.Inject;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Marcin Grzejszczak
* @author Anatoliy Balakirev
* @author Shannon Pamperl
*/
public class ContractVerifierExtension {
private static final Log log = LogFactory.getLog(ContractVerifierExtension.class);
/**
* For which unit test library tests should be generated
*/
private Property<TestFramework> testFramework;
/**
* Which mechanism should be used to invoke REST calls during tests
*/
private Property<TestMode> testMode;
/**
* Base package for generated tests
*/
private Property<String> basePackageForTests;
/**
* Class which all generated tests should extend
*/
private Property<String> baseClassForTests;
/**
* Suffix for generated test classes, like Spec or Test
*/
private Property<String> nameSuffixForTests;
/**
* Rule class that should be added to generated tests
*/
private Property<String> ruleClassForTests;
/**
* Patterns that should not be taken into account for processing
*/
private ListProperty<String> excludedFiles;
/**
* Patterns that should be taken into account for processing
*/
private ListProperty<String> includedFiles;
/**
* Patterns for which generated tests should be @Ignored
*/
private ListProperty<String> ignoredFiles;
/**
* Imports that should be added to generated tests
*/
private ListProperty<String> imports;
/**
* Static imports that should be added to generated tests
*/
private ListProperty<String> staticImports;
/**
* Directory containing contracts written using the GroovyDSL
*/
private DirectoryProperty contractsDslDir;
/**
* Test source directory where tests generated from Groovy DSL should be placed
*/
private DirectoryProperty generatedTestSourcesDir;
/**
* Test resource directory where tests generated from Groovy DSL should be referenced
*/
private DirectoryProperty generatedTestResourcesDir;
/**
* 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
*/
private DirectoryProperty stubsOutputDir;
/**
* Suffix for the generated Stubs Jar task
*/
private Property<String> stubsSuffix;
/**
* Incubating feature. You can check the size of JSON arrays. If not turned on
* explicitly will be disabled.
*/
private Property<Boolean> assertJsonSize;
/**
* When enabled, this flag will tell stub runner to throw an exception when no stubs /
* contracts were found.
*/
private Property<Boolean> failOnNoContracts;
/**
* If set to true then if any contracts that are in progress are found, will break the
* build. On the producer side you need to be explicit about the fact that you have
* contracts in progress and take into consideration that you might be causing false
* positive test execution results on the consumer side.
*/
private Property<Boolean> failOnInProgress;
private ContractRepository contractRepository;
/**
* Dependency that contains packaged contracts
*/
private Dependency contractDependency;
/**
* The path in the JAR with all the contracts where contracts for this particular service lay.
* If not provided will be resolved to {@code groupid/artifactid}. Example:
* </p>
* If {@code groupid} is {@code com.example} and {@code artifactid} is {@code service} then the resolved path will be
* {@code /com/example/artifactid}
*/
private Property<String> contractsPath;
/**
* Picks the mode in which stubs will be found and registered
*/
private Property<StubRunnerProperties.StubsMode> contractsMode;
/**
* A package that contains all the base clases for generated tests. If your contract resides in a location
* {@code src/test/resources/contracts/com/example/v1/} and you provide the {@code packageWithBaseClasses}
* value to {@code com.example.contracts.base} then we will search for a test source file that will
* have the package {@code com.example.contracts.base} and name {@code ExampleV1Base}. As you can see
* it will take the two last folders to and attach {@code Base} to its name.
*/
private Property<String> packageWithBaseClasses;
/**
* A way to override any base class mappings. The keys are regular expressions on the package name
* and the values FQN to a base class for that given expression.
* </p>
* Example of a mapping
* </p>
* {@code .*.com.example.v1..*} -> {@code com.example.SomeBaseClass}
* </p>
* When a contract's package matches the provided regular expression then extending class will be the one
* provided in the map - in this case {@code com.example.SomeBaseClass}
*/
private BaseClassMapping baseClassMappings;
/**
* If set to true then the {@code target} or {@code build} folders are getting
* excluded from any operations. This is used out of the box when working with
* common repo with contracts.
*/
private Property<Boolean> excludeBuildFolders;
/**
* If set to {@code true} will not assert whether the downloaded stubs / contract
* JAR was downloaded from a remote location or a local one(only applicable to Maven repos, not Git or Pact)
*
* @deprecated - with 2.1.0 this option is redundant
*/
@Deprecated
private Property<Boolean> contractsSnapshotCheckSkip;
/**
* If set to {@code false} will NOT delete stubs from a temporary
* folder after running tests
*/
private Property<Boolean> deleteStubsAfterTest;
/**
* If {@code true} then will convert contracts to a YAML representation
*/
private Property<Boolean> convertToYaml;
/**
* Map of properties that can be passed to custom {@link org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder}
*/
private MapProperty<String, String> contractsProperties;
/**
* Is set to true will not provide the default publication task
*/
private Property<Boolean> disableStubPublication;
@Inject
public ContractVerifierExtension(ProjectLayout layout, ObjectFactory objects) {
this.testFramework = objects.property(TestFramework.class).convention(TestFramework.JUNIT);
this.testMode = objects.property(TestMode.class).convention(TestMode.MOCKMVC);
this.basePackageForTests = objects.property(String.class);
this.baseClassForTests = objects.property(String.class);
this.nameSuffixForTests = objects.property(String.class);
this.ruleClassForTests = objects.property(String.class);
this.excludedFiles = objects.listProperty(String.class).convention(new ArrayList<>());
this.includedFiles = objects.listProperty(String.class).convention(new ArrayList<>());
this.ignoredFiles = objects.listProperty(String.class).convention(new ArrayList<>());
this.imports = objects.listProperty(String.class).convention(new ArrayList<>());
this.staticImports = objects.listProperty(String.class).convention(new ArrayList<>());
this.contractsDslDir = objects.directoryProperty().convention(layout.getProjectDirectory().dir("src/test/resources/contracts"));
this.generatedTestSourcesDir = objects.directoryProperty().convention(layout.getBuildDirectory().dir("generated-test-sources/contracts"));
this.generatedTestResourcesDir = objects.directoryProperty().convention(layout.getBuildDirectory().dir("generated-test-resources/contracts"));
this.stubsOutputDir = objects.directoryProperty().convention(layout.getBuildDirectory().dir("stubs"));
this.stubsSuffix = objects.property(String.class).convention("stubs");
this.assertJsonSize = objects.property(Boolean.class).convention(false);
this.failOnNoContracts = objects.property(Boolean.class).convention(true);
this.failOnInProgress = objects.property(Boolean.class).convention(true);
this.contractRepository = objects.newInstance(ContractRepository.class);
this.contractDependency = objects.newInstance(Dependency.class);
this.contractsPath = objects.property(String.class);
this.contractsMode = objects.property(StubRunnerProperties.StubsMode.class).convention(StubRunnerProperties.StubsMode.CLASSPATH);
this.packageWithBaseClasses = objects.property(String.class);
this.baseClassMappings = objects.newInstance(BaseClassMapping.class);
this.excludeBuildFolders = objects.property(Boolean.class).convention(false);
this.contractsSnapshotCheckSkip = objects.property(Boolean.class).convention(false);
this.deleteStubsAfterTest = objects.property(Boolean.class).convention(true);
this.convertToYaml = objects.property(Boolean.class).convention(false);
this.contractsProperties = objects.mapProperty(String.class, String.class).convention(new HashMap<>());
this.disableStubPublication = objects.property(Boolean.class).convention(false);
}
@Deprecated
public void setTargetFramework(TestFramework targetFramework) {
log.warn("Please use the [testFramework] field. This one is deprecated");
this.testFramework.set(targetFramework);
}
@Deprecated
public TestFramework getTargetFramework() {
return getTestFramework().get();
}
public Property<TestFramework> getTestFramework() {
return testFramework;
}
public void setTestFramework(TestFramework testFramework) {
this.testFramework.set(testFramework);
}
public void setTestFramework(String testFramework) {
if (testFramework != null) {
this.testFramework.set(TestFramework.valueOf(testFramework.toUpperCase()));
}
}
public Property<TestMode> getTestMode() {
return testMode;
}
public void setTestMode(TestMode testMode) {
this.testMode.set(testMode);
}
public void setTestMode(String testMode) {
if (testMode != null) {
this.testMode.set(TestMode.valueOf(testMode.toUpperCase()));
}
}
public Property<String> getBasePackageForTests() {
return basePackageForTests;
}
public void setBasePackageForTests(String basePackageForTests) {
this.basePackageForTests.set(basePackageForTests);
}
public Property<String> getBaseClassForTests() {
return baseClassForTests;
}
public void setBaseClassForTests(String baseClassForTests) {
this.baseClassForTests.set(baseClassForTests);
}
public Property<String> getNameSuffixForTests() {
return nameSuffixForTests;
}
public void setNameSuffixForTests(String nameSuffixForTests) {
this.nameSuffixForTests.set(nameSuffixForTests);
}
public Property<String> getRuleClassForTests() {
return ruleClassForTests;
}
public void setRuleClassForTests(String ruleClassForTests) {
this.ruleClassForTests.set(ruleClassForTests);
}
public ListProperty<String> getExcludedFiles() {
return excludedFiles;
}
public void setExcludedFiles(List<String> excludedFiles) {
this.excludedFiles.set(excludedFiles);
}
public ListProperty<String> getIncludedFiles() {
return includedFiles;
}
public void setIncludedFiles(List<String> includedFiles) {
this.includedFiles.set(includedFiles);
}
public ListProperty<String> getIgnoredFiles() {
return ignoredFiles;
}
public void setIgnoredFiles(List<String> ignoredFiles) {
this.ignoredFiles.set(ignoredFiles);
}
public ListProperty<String> getImports() {
return imports;
}
public void setImports(String[] imports) {
this.imports.set(new ArrayList<>(Arrays.asList(imports)));
}
public void setInputs(List<String> imports) {
this.imports.set(imports);
}
public ListProperty<String> getStaticImports() {
return staticImports;
}
public void setStaticImports(String[] staticImports) {
this.staticImports.set(new ArrayList<>(Arrays.asList(staticImports)));
}
public void setStaticImports(List<String> staticImports) {
this.staticImports.set(staticImports);
}
public DirectoryProperty getContractsDslDir() {
return contractsDslDir;
}
public void setContractsDslDir(File contractsDslDir) {
this.contractsDslDir.set(contractsDslDir);
}
public DirectoryProperty getGeneratedTestSourcesDir() {
return generatedTestSourcesDir;
}
public void setGeneratedTestSourcesDir(File generatedTestSourcesDir) {
this.generatedTestSourcesDir.set(generatedTestSourcesDir);
}
public DirectoryProperty getGeneratedTestResourcesDir() {
return generatedTestResourcesDir;
}
public void setGeneratedTestResourcesDir(File generatedTestResourcesDir) {
this.generatedTestResourcesDir.set(generatedTestResourcesDir);
}
public DirectoryProperty getStubsOutputDir() {
return stubsOutputDir;
}
public void setStubsOutputDir(File stubsOutputDir) {
this.stubsOutputDir.set(stubsOutputDir);
}
public Property<String> getStubsSuffix() {
return stubsSuffix;
}
public void setStubsSuffix(String stubsSuffix) {
this.stubsSuffix.set(stubsSuffix);
}
public Property<Boolean> getAssertJsonSize() {
return assertJsonSize;
}
public void setAssertJsonSize(boolean assertJsonSize) {
this.assertJsonSize.set(assertJsonSize);
}
public Property<Boolean> getFailOnNoContracts() {
return failOnNoContracts;
}
public void setFailOnNoContracts(boolean failOnNoContracts) {
this.failOnNoContracts.set(failOnNoContracts);
}
public Property<Boolean> getFailOnInProgress() {
return failOnInProgress;
}
public void setFailOnInProgress(boolean failOnInProgress) {
this.failOnInProgress.set(failOnInProgress);
}
public ContractRepository getContractRepository() {
return contractRepository;
}
public void contractRepository(Action<ContractRepository> action) {
action.execute(contractRepository);
}
public Dependency getContractDependency() {
return contractDependency;
}
public void contractDependency(Action<Dependency> action) {
action.execute(contractDependency);
}
public Property<String> getContractsPath() {
return contractsPath;
}
public void setContractsPath(String contractsPath) {
this.contractsPath.set(contractsPath);
}
public Property<StubRunnerProperties.StubsMode> getContractsMode() {
return contractsMode;
}
public void setContractsMode(StubRunnerProperties.StubsMode contractsMode) {
this.contractsMode.set(contractsMode);
}
public void setContractsMode(String contractsMode) {
if (contractsMode != null) {
this.contractsMode.set(StubRunnerProperties.StubsMode.valueOf(contractsMode.toUpperCase()));
}
}
public Property<String> getPackageWithBaseClasses() {
return packageWithBaseClasses;
}
public void setPackageWithBaseClasses(String packageWithBaseClasses) {
this.packageWithBaseClasses.set(packageWithBaseClasses);
}
public BaseClassMapping getBaseClassMappings() {
return baseClassMappings;
}
public void setBaseClassMappings(Map<String, String> baseClassMappings) {
this.baseClassMappings.getBaseClassMappings().set(baseClassMappings);
}
public void baseClassMappings(Action<BaseClassMapping> action) {
action.execute(baseClassMappings);
}
public Property<Boolean> getExcludeBuildFolders() {
return excludeBuildFolders;
}
public void setExcludeBuildFolders(boolean excludeBuildFolders) {
this.excludeBuildFolders.set(excludeBuildFolders);
}
public Property<Boolean> getContractsSnapshotCheckSkip() {
return contractsSnapshotCheckSkip;
}
public void setContractsSnapshotCheckSkip(boolean contractsSnapshotCheckSkip) {
this.contractsSnapshotCheckSkip.set(contractsSnapshotCheckSkip);
}
public Property<Boolean> getDeleteStubsAfterTest() {
return deleteStubsAfterTest;
}
public void setDeleteStubsAfterTest(boolean deleteStubsAfterTest) {
this.deleteStubsAfterTest.set(deleteStubsAfterTest);
}
public Property<Boolean> getConvertToYaml() {
return convertToYaml;
}
public void setConvertToYaml(boolean convertToYaml) {
this.convertToYaml.set(convertToYaml);
}
public MapProperty<String, String> getContractsProperties() {
return contractsProperties;
}
public void setContractsProperties(Map<String, String> contractsProperties) {
this.contractsProperties.set(contractsProperties);
}
// use standard setter instead
@Deprecated
public void contractsProperties(Map<String, String> map) {
contractsProperties.set(map);
}
public Property<Boolean> getDisableStubPublication() {
return disableStubPublication;
}
public void setDisableStubPublication(boolean disableStubPublication) {
this.disableStubPublication.set(disableStubPublication);
}
public static class Dependency {
private Property<String> groupId;
private Property<String> artifactId;
private Property<String> version;
private Property<String> classifier;
private Property<String> stringNotation;
@Inject
public Dependency(ObjectFactory objects) {
groupId = objects.property(String.class);
artifactId = objects.property(String.class);
version = objects.property(String.class);
classifier = objects.property(String.class);
stringNotation = objects.property(String.class);
}
@Input
@Optional
public Property<String> getGroupId() {
return groupId;
}
public void setGroupId(String groupId) {
this.groupId.set(groupId);
}
@Input
@Optional
public Property<String> getArtifactId() {
return artifactId;
}
public void setArtifactId(String artifactId) {
this.artifactId.set(artifactId);
}
@Input
@Optional
public Property<String> getVersion() {
return version;
}
public void setVersion(String version) {
this.version.set(version);
}
@Input
@Optional
public Property<String> getClassifier() {
return classifier;
}
public void setClassifier(String classifier) {
this.classifier.set(classifier);
}
@Input
@Optional
public Property<String> getStringNotation() {
return stringNotation;
}
public void setStringNotation(String stringNotation) {
this.stringNotation.set(stringNotation);
}
@Override
public String toString() {
return "Dependency{" +
"groupId=" + groupId.getOrNull() +
", artifactId=" + artifactId.getOrNull() +
", classifier=" + classifier.getOrNull() +
", version=" + version.getOrNull() +
", stringNotation=" + stringNotation.getOrNull() +
'}';
}
}
public static class BaseClassMapping {
private final MapProperty<String, String> baseClassMappings;
@Inject
public BaseClassMapping(ObjectFactory objects) {
this.baseClassMappings = objects.mapProperty(String.class, String.class).convention(new HashMap<>());
}
public MapProperty<String, String> getBaseClassMappings() {
return baseClassMappings;
}
public void baseClassMapping(String packageRegex, String fqnBaseClass) {
baseClassMappings.put(packageRegex, fqnBaseClass);
}
public void baseClassMapping(Map<String, String> mapping) {
baseClassMappings.putAll(mapping);
}
}
// This class is used as an input to the tasks, so all fields are marked as `@Input` to allow incremental build
public static class ContractRepository {
private Property<String> repositoryUrl;
private Property<String> username;
private Property<String> password;
private Property<Integer> proxyPort;
private Property<String> proxyHost;
/**
* If set to true then will cache the folder where non snapshot contract artifacts got downloaded.
*
* Not used any more, as we switched to Gradle's incremental build.
*/
private Property<Boolean> cacheDownloadedContracts;
@Inject
public ContractRepository(ObjectFactory objects) {
this.repositoryUrl = objects.property(String.class);
this.username = objects.property(String.class);
this.password = objects.property(String.class);
this.proxyHost = objects.property(String.class);
this.proxyPort = objects.property(Integer.class);
this.cacheDownloadedContracts = objects.property(Boolean.class).convention(true);
}
@Input
@Optional
public Property<String> getRepositoryUrl() {
return repositoryUrl;
}
public void setRepositoryUrl(String repositoryUrl) {
this.repositoryUrl.set(repositoryUrl);
}
// favor property assignment
@Deprecated
public void repositoryUrl(String repositoryUrl) {
this.repositoryUrl.set(repositoryUrl);
}
@Input
@Optional
public Property<String> getUsername() {
return username;
}
public void setUsername(String username) {
this.username.set(username);
}
// favor property assignment
@Deprecated
public void username(String username) {
this.username.set(username);
}
@Input
@Optional
public Property<String> getPassword() {
return password;
}
public void setPassword(String password) {
this.password.set(password);
}
// favor property assignment
@Deprecated
public void password(String password) {
this.password.set(password);
}
@Input
@Optional
public Property<String> getProxyHost() {
return proxyHost;
}
public void setProxyHost(String proxyHost) {
this.proxyHost.set(proxyHost);
}
// favor property assignment
@Deprecated
public void proxyHost(String proxyHost) {
this.proxyHost.set(proxyHost);
}
@Input
@Optional
public Property<Integer> getProxyPort() {
return proxyPort;
}
// favor unwrapped int
@Deprecated
public void setProxyPort(Integer proxyPort) {
this.proxyPort.set(proxyPort);
}
public void setProxyPort(int proxyPort) {
Assert.state(0 < proxyPort && proxyPort <= 65536, "Proxy port should be between 1 and 65536");
this.proxyPort.set(proxyPort);
}
@Internal
@Deprecated
public Property<Boolean> getCacheDownloadedContracts() {
return cacheDownloadedContracts;
}
@Deprecated
public void setCacheDownloadedContracts(boolean cacheDownloadedContracts) {
this.cacheDownloadedContracts.set(cacheDownloadedContracts);
}
@Override
public String toString() {
return "ContractRepository{" +
"repositoryUrl=" + repositoryUrl.getOrNull() +
", username=" + username.getOrNull() +
", password=" + password.getOrNull() +
", proxyPort=" + proxyPort.getOrNull() +
", proxyHost=" + proxyHost.getOrNull() +
", cacheDownloadedContracts=" + cacheDownloadedContracts.get() +
'}';
}
}
}

View File

@@ -151,7 +151,7 @@ class GenerateServerTestsTask extends DefaultTask {
staticImports: extension.staticImports,
testMode: extension.testMode,
testFramework: extension.testFramework,
baseClassMappings: extension.baseClassMappings,
baseClassMappings: extension.baseClassMappings.getBaseClassMappings(),
assertJsonSize: extension.assertJsonSize,
failOnInProgress: extension.failOnInProgress,

View File

@@ -55,7 +55,6 @@ class SpringCloudContractVerifierGradlePlugin implements Plugin<Project> {
this.project = project
project.plugins.apply(GroovyPlugin)
ContractVerifierExtension extension = project.extensions.create(EXTENSION_NAME, ContractVerifierExtension)
setConfigurationDefaults(extension)
TaskProvider<ContractsCopyTask> copyContracts = createAndConfigureCopyContractsTask(extension)
TaskProvider<GenerateClientStubsFromDslTask> generateClientStubs = createAndConfigureGenerateClientStubs(extension, copyContracts)
@@ -101,16 +100,6 @@ class SpringCloudContractVerifierGradlePlugin implements Plugin<Project> {
}
}
private void setConfigurationDefaults(ContractVerifierExtension extension) {
extension.with {
it.contractsDslDir.convention(project.layout.projectDirectory.dir("src/test/resources/contracts"))
it.generatedTestSourcesDir.convention(project.layout.getBuildDirectory().dir("generated-test-sources/contracts"))
it.generatedTestResourcesDir.convention(project.layout.getBuildDirectory().dir("generated-test-resources/contracts"))
it.stubsOutputDir.convention(project.layout.getBuildDirectory().dir("stubs"))
}
}
private void createGenerateTestsTask(ContractVerifierExtension extension, TaskProvider<ContractsCopyTask> copyContracts) {
TaskProvider<GenerateServerTestsTask> task = project.tasks.register(GenerateServerTestsTask.TASK_NAME, GenerateServerTestsTask)
task.configure {

View File

@@ -51,18 +51,6 @@ abstract class ContractVerifierIntegrationSpec extends Specification {
protected void setupForProject(String projectRoot) {
copyResourcesToRoot(projectRoot)
String gradlePluginSysProp = System.getProperty("contract-gradle-plugin-libs-dir")
String gradlePluginLibsDir = (gradlePluginSysProp ?: new File("build/").absolutePath.toString()).replace('\\', '\\\\')
buildFile.write """
buildscript {
dependencies {
classpath fileTree(dir: '$gradlePluginLibsDir', include: '*.jar')
}
}
""" + buildFile.text
// Extending buildscript is required when 'apply' is used.
// 'GradleRunner#withPluginClasspath' can be used when plugin is added using 'plugins { id...'
}
protected void switchToJunitTestFramework() {
@@ -105,7 +93,8 @@ abstract class ContractVerifierIntegrationSpec extends Specification {
return GradleRunner.create()
.withProjectDir(testProjectDir)
.withArguments(tasks)
.withDebug(true)
.withPluginClasspath()
// .withDebug(true)
.forwardOutput()
.build()
}

View File

@@ -0,0 +1,40 @@
/*
* 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.plugin
import java.nio.file.Files
import java.nio.file.Path
import static java.nio.charset.StandardCharsets.UTF_8
abstract class ContractVerifierKotlinIntegrationSpec extends ContractVerifierIntegrationSpec {
public static final String SPOCK = "testFramework.set(TestFramework.SPOCK)"
public static final String JUNIT = "testFramework.set(TestFramework.JUNIT)"
@Override
protected File getBuildFile() {
return new File(testProjectDir, 'build.gradle.kts')
}
@Override
protected void switchToJunitTestFramework(String from, String to) {
Path path = buildFile.toPath()
String content = new StringBuilder(new String(Files.readAllBytes(path), UTF_8)).replaceAll(SPOCK, JUNIT)
.replaceAll(from, to)
Files.write(path, content.getBytes(UTF_8))
}
}

View File

@@ -1,5 +1,7 @@
package org.springframework.cloud.contract.verifier.plugin
import org.gradle.api.Project
import org.gradle.api.file.ProjectLayout
import org.gradle.api.internal.project.DefaultProject
import org.gradle.api.model.ObjectFactory
import org.gradle.api.plugins.GroovyPlugin
@@ -89,16 +91,16 @@ class ContractVerifierSpec extends Specification {
def "should compile"() {
given:
ObjectFactory objectFactory = Stub(ObjectFactory)
ContractVerifierExtension extension = new ContractVerifierExtension(objectFactory)
project.plugins.apply(SpringCloudContractVerifierGradlePlugin)
ContractVerifierExtension extension = project.getExtensions().findByType(ContractVerifierExtension)
extension.with {
// tag::package_with_base_classes[]
packageWithBaseClasses.set('com.example.base')
packageWithBaseClasses = 'com.example.base'
// end::package_with_base_classes[]
// tag::base_class_mappings[]
baseClassForTests.set("com.example.FooBase")
baseClassForTests = "com.example.FooBase"
baseClassMappings {
baseClassMapping('.*/com/.*', 'com.example.ComBase')
baseClassMapping('.*/bar/.*': 'com.example.BarBase')

View File

@@ -1,67 +0,0 @@
/*
* 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.plugin
import org.gradle.testkit.runner.BuildResult
import org.junit.Ignore
import spock.lang.Stepwise
import static org.gradle.testkit.runner.TaskOutcome.UP_TO_DATE
@Stepwise
@Ignore
class SampleProjectSpec extends ContractVerifierIntegrationSpec {
def setup() {
setupForProject("functionalTest/sampleProject")
runTasksSuccessfully('clean')
//delete accidental output when previously importing SimpleBoot into Idea to tweak it
}
def "should pass basic flow for Spock"() {
given:
assert fileExists('build.gradle')
when:
String[] args = ["check", "publishToMavenLocal", "--debug"] as String[]
if (WORK_OFFLINE) {
args << "--offline"
}
runTasksSuccessfully(args)
then:
jarContainsContractVerifierContracts('fraudDetectionService/build/libs')
when: "running generation without change inputs"
BuildResult secondExecutionResult = runTasksSuccessfully()
then: "tasks should be up-to-date"
validateTasksOutcome(secondExecutionResult, UP_TO_DATE, 'generateClientStubs', 'generateContractTests', 'copyContracts')
}
def "should pass basic flow for JUnit"() {
given:
switchToJunitTestFramework()
assert fileExists('build.gradle')
when:
runTasksSuccessfully(checkAndPublishToMavenLocal())
then:
jarContainsContractVerifierContracts('fraudDetectionService/build/libs')
when: "running generation without change inputs"
BuildResult secondExecutionResult = runTasksSuccessfully()
then: "tasks should be up-to-date"
validateTasksOutcome(secondExecutionResult, UP_TO_DATE, 'generateClientStubs', 'generateContractTests', 'copyContracts')
}
}

View File

@@ -16,46 +16,32 @@
package org.springframework.cloud.contract.verifier.plugin
import org.gradle.testkit.runner.BuildResult
import spock.lang.Stepwise
import spock.lang.Ignore
@Stepwise
@Ignore("Flaky")
class SampleJerseyProjectSpec extends ContractVerifierIntegrationSpec {
class ScenarioProjectKotlinSpec extends ContractVerifierKotlinIntegrationSpec {
def setup() {
setupForProject("functionalTest/sampleJerseyProject")
setupForProject("functionalTest/scenarioProjectKotlin")
runTasksSuccessfully('clean')
//delete accidental output when previously importing SimpleBoot into Idea to tweak it
}
def "should pass basic flow for Spock"() {
given:
assert fileExists('build.gradle')
expect:
BuildResult result = runTasksSuccessfully(checkAndPublishToMavenLocal())
jarContainsContractVerifierContracts('fraudDetectionService/build/libs')
!result.output.contains("You've switched off the stub publication")
}
def "should pass basic flow for Spock with disabled publication"() {
given:
assert fileExists('build.gradle')
expect:
String[] args = (checkAndPublishToMavenLocal().toList() << "-PdisablePublication") as String[]
BuildResult result = runTasksSuccessfully(args)
!fileExists('fraudDetectionService/build/libs')
result.output.contains("You've switched off the stub publication")
}
def "should pass basic flow for JUnit"() {
given:
switchToJunitTestFramework()
assert fileExists('build.gradle')
assert fileExists('build.gradle.kts')
expect:
runTasksSuccessfully(checkAndPublishToMavenLocal())
jarContainsContractVerifierContracts('fraudDetectionService/build/libs')
}
def "should pass basic flow for JUnit"() {
given:
assert fileExists('build.gradle.kts')
expect:
switchToJunitTestFramework()
runTasksSuccessfully(checkAndPublishToMavenLocal())
jarContainsContractVerifierContracts('fraudDetectionService/build/libs')
}
}

View File

@@ -1,160 +0,0 @@
/*
* 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.
*/
buildscript {
repositories {
mavenLocal()
mavenCentral()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/release" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${bootVersion}")
}
}
apply plugin: 'checkstyle'
allprojects {
group = 'com.example.jersey'
}
ext {
spockVersion = '1.0-groovy-2.4'
contractVerifierStubsBaseDirectory = 'src/test/resources/stubs'
}
subprojects {
apply plugin: 'groovy'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
mavenLocal()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/release" }
}
dependencies {
testCompile "org.codehaus.groovy:groovy"
testCompile("org.spockframework:spock-core:$spockVersion") {
exclude(group: 'org.codehaus.groovy')
}
testCompile 'junit:junit:4.12'
testCompile "com.github.tomakehurst:wiremock:${wiremockVersion}"
testCompile "com.toomuchcoding.jsonassert:jsonassert:${jsonAssertVersion}"
testCompile "org.springframework.cloud:spring-cloud-contract-verifier:${verifierVersion}"
}
}
configure([project(':fraudDetectionService'), project(':loanApplicationService')]) {
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'maven-publish'
jar {
version = '0.0.1'
}
bootJar {
enabled = false
}
configurations {
compile.exclude module: "spring-boot-starter-tomcat"
}
dependencies {
compile 'org.springframework.boot:spring-boot-starter-jersey'
compile 'org.springframework.boot:spring-boot-starter-jetty'
testRuntime("org.spockframework:spock-spring:$spockVersion") {
exclude(group: 'org.codehaus.groovy')
}
testCompile "org.mockito:mockito-core"
testCompile "org.springframework:spring-test"
testCompile "org.springframework.boot:spring-boot-test"
testCompile("com.github.tomakehurst:wiremock:${wiremockVersion}") {
exclude group: 'org.eclipse.jetty'
}
}
task cleanup(type: Delete) {
delete 'src/test/resources/mappings', 'src/test/resources/stubs'
}
clean.dependsOn('cleanup')
test {
testLogging {
exceptionFormat = 'full'
}
}
}
configure(project(':fraudDetectionService')) {
test.dependsOn('generateClientStubs')
apply plugin: 'spring-cloud-contract'
ext {
contractsDir = file("mappings")
stubsOutputDirRoot = file("${project.buildDir}/production/${project.name}-stubs/")
}
tasks.create(type: Jar, name: 'verifierStubsJar', dependsOn: 'generateClientStubs') {
baseName = project.name
classifier = contracts.stubsSuffix
from ext.stubsOutputDir
}
contracts {
contractsMode = "REMOTE"
testFramework = 'Spock'
testMode = 'JaxRsClient'
baseClassForTests = 'org.springframework.cloud.MvcSpec'
contractDependency {
stringNotation("com.example:jersey-contracts:+:")
}
contractRepository {
repositoryUrl = "file://" + file("${project.rootDir.absolutePath}/m2repo/repository").absolutePath
}
generatedTestSourcesDir = file("${project.buildDir}/generated-test-sources/")
stubsOutputDir = stubsOutputDirRoot
disableStubPublication(project.hasProperty("disablePublication"))
}
}
configure(project(':loanApplicationService')) {
task copyCollaboratorStubs(type: Copy) {
File fraudBuildDir = project(':fraudDetectionService').buildDir
from(new File(fraudBuildDir, "/production/${project(':fraudDetectionService').name}-stubs/")) {
include '**/*.json'
}
into "src/test/resources/mappings"
}
test.dependsOn('copyCollaboratorStubs')
}

View File

@@ -1,64 +0,0 @@
/*
* 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.frauddetection;
import java.math.BigDecimal;
import org.springframework.cloud.frauddetection.model.FraudCheck;
import org.springframework.cloud.frauddetection.model.FraudCheckResult;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestBody;
import static org.springframework.cloud.frauddetection.model.FraudCheckStatus.FRAUD;
import static org.springframework.cloud.frauddetection.model.FraudCheckStatus.OK;
@Controller
@Path("/")
public class FraudDetectionController {
private static final String FRAUD_SERVICE_JSON_VERSION_1 = "application/vnd.fraud.v1+json";
private static final String NO_REASON = null;
private static final String AMOUNT_TOO_HIGH = "Amount too high";
private static final BigDecimal MAX_AMOUNT = new BigDecimal("5000");
@PUT
@Path("/fraudcheck")
@Produces(FRAUD_SERVICE_JSON_VERSION_1)
@Consumes(FRAUD_SERVICE_JSON_VERSION_1)
public FraudCheckResult fraudCheck(
@RequestBody(required = false) FraudCheck fraudCheck) {
if (amountGreaterThanThreshold(fraudCheck)) {
return new FraudCheckResult(FRAUD, AMOUNT_TOO_HIGH);
}
return new FraudCheckResult(OK, NO_REASON);
}
@GET
@Path("/frauds/name")
public String cookie(@CookieParam("name") Cookie name,
@CookieParam("name2") Cookie name2) {
return name.getValue() + " " + name2.getValue();
}
private boolean amountGreaterThanThreshold(FraudCheck fraudCheck) {
return MAX_AMOUNT.compareTo(fraudCheck.getLoanAmount()) < 0;
}
}

View File

@@ -1,75 +0,0 @@
/*
* 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
import javax.ws.rs.client.Client
import javax.ws.rs.client.ClientBuilder
import javax.ws.rs.client.WebTarget
import javax.ws.rs.core.UriBuilder
import org.eclipse.jetty.server.Server
import org.eclipse.jetty.servlet.ServletContextHandler
import org.eclipse.jetty.servlet.ServletHolder
import org.glassfish.jersey.client.ClientConfig
import spock.lang.Shared
import spock.lang.Specification
import org.springframework.cloud.frauddetection.FraudDetectionController
import static org.springframework.util.SocketUtils.findAvailableTcpPort
abstract class MvcSpec extends Specification {
@Shared
WebTarget webTarget
@Shared
private Server server
@Shared
private Client client
def setupSpec() {
int port = findAvailableTcpPort(8000)
URI baseUri = UriBuilder.fromUri("http://localhost").port(port).build()
// Create Server
Server server = new Server(port)
// Configure ServletContextHandler
ServletContextHandler context = new ServletContextHandler(ServletContextHandler.SESSIONS)
context.setContextPath("/")
server.setHandler(context)
// Create Servlet Container
ServletHolder jerseyServlet = context.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*")
jerseyServlet.setInitOrder(0)
// Tells the Jersey Servlet which REST service/class to load.
jerseyServlet.setInitParameter("jersey.config.server.provider.classnames", FraudDetectionController.class.getCanonicalName())
// Start the server
server.start()
ClientConfig clientConfig = new ClientConfig()
client = ClientBuilder.newClient(clientConfig)
webTarget = client.target(baseUri)
}
def cleanupSpec() {
client?.close()
server?.stop()
}
void assertThatRejectionReasonIsNull(def rejectionReason) {
assert !rejectionReason
}
}

View File

@@ -1,95 +0,0 @@
/*
* 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;
import java.net.URI;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.UriBuilder;
import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.servlet.ServletContextHandler;
import org.eclipse.jetty.servlet.ServletHolder;
import org.glassfish.jersey.client.ClientConfig;
import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.springframework.cloud.frauddetection.FraudDetectionController;
import static org.springframework.util.SocketUtils.findAvailableTcpPort;
public abstract class MvcTest {
public static WebTarget webTarget;
private static Server server;
private static Client client;
@BeforeClass
public static void setupTest() throws Exception {
int port = findAvailableTcpPort(10000);
URI baseUri = UriBuilder.fromUri("http://localhost").port(port).build();
// Create Server
Server server = new Server(port);
// Configure ServletContextHandler
ServletContextHandler context = new ServletContextHandler(
ServletContextHandler.SESSIONS);
context.setContextPath("/");
server.setHandler(context);
// Create Servlet Container
ServletHolder jerseyServlet = context
.addServlet(org.glassfish.jersey.servlet.ServletContainer.class, "/*");
jerseyServlet.setInitOrder(0);
// Tells the Jersey Servlet which REST service/class to load.
jerseyServlet.setInitParameter("jersey.config.server.provider.classnames",
FraudDetectionController.class.getCanonicalName());
// Start the server
server.start();
ClientConfig clientConfig = new ClientConfig();
client = ClientBuilder.newClient(clientConfig);
webTarget = client.target(baseUri);
try {
server.start();
}
catch (Exception e) {
e.printStackTrace();
}
}
@AfterClass
public static void cleanupTest() {
if (client != null) {
client.close();
}
if (server != null) {
try {
server.stop();
}
catch (Exception e) {
e.printStackTrace();
}
}
}
public void assertThatRejectionReasonIsNull(Object rejectionReason) {
assert rejectionReason == null;
}
}

View File

@@ -1,33 +0,0 @@
/*
* 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.frauddetection;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
@Configuration
@EnableAutoConfiguration
@ComponentScan
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}

View File

@@ -1,31 +0,0 @@
{
"id": "856bd753-2488-4549-b84f-512e851958a9",
"request": {
"url": "/fraudcheck",
"method": "PUT",
"headers": {
"Content-Type": {
"equalTo": "application/vnd.fraud.v1+json"
}
},
"bodyPatterns": [
{
"matchesJsonPath": "$[?(@.['loanAmount'] == 99999)]"
},
{
"matchesJsonPath": "$[?(@.['clientPesel'] =~ /[0-9]{10}/)]"
}
]
},
"response": {
"status": 200,
"body": "{\"fraudCheckStatus\":\"FRAUD\",\"rejectionReason\":\"Amount too high\"}",
"headers": {
"Content-Type": "application/vnd.fraud.v1+json"
},
"transformers": [
"response-template"
]
},
"uuid": "856bd753-2488-4549-b84f-512e851958a9"
}

View File

@@ -1,31 +0,0 @@
{
"id": "263aac46-1534-497d-9cc6-114a29ffa0de",
"request": {
"url": "/fraudcheck",
"method": "PUT",
"headers": {
"Content-Type": {
"equalTo": "application/vnd.fraud.v1+json"
}
},
"bodyPatterns": [
{
"matchesJsonPath": "$[?(@.['loanAmount'] == 123.123)]"
},
{
"matchesJsonPath": "$[?(@.['clientPesel'] =~ /[0-9]{10}/)]"
}
]
},
"response": {
"status": 200,
"body": "{\"fraudCheckStatus\":\"OK\",\"rejectionReason\":null}",
"headers": {
"Content-Type": "application/vnd.fraud.v1+json"
},
"transformers": [
"response-template"
]
},
"uuid": "263aac46-1534-497d-9cc6-114a29ffa0de"
}

View File

@@ -1,26 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"
xmlns="http://maven.apache.org/POM/4.0.0">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>jersey-contracts</artifactId>
<version>0.0.1-SNAPSHOT</version>
<packaging>pom</packaging>
</project>

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<metadata modelVersion="1.1.0">
<groupId>com.example</groupId>
<artifactId>jersey-contracts</artifactId>
<version>0.0.1-SNAPSHOT</version>
<versioning>
<snapshot>
<localCopy>true</localCopy>
</snapshot>
<lastUpdated>20160916125313</lastUpdated>
<snapshotVersions>
<snapshotVersion>
<extension>jar</extension>
<value>0.0.1-SNAPSHOT</value>
<updated>20170916125313</updated>
</snapshotVersion>
<snapshotVersion>
<extension>pom</extension>
<value>0.0.1-SNAPSHOT</value>
<updated>20160916125313</updated>
</snapshotVersion>
</snapshotVersions>
</versioning>
</metadata>

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
~ 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.
-->
<metadata>
<groupId>com.example</groupId>
<artifactId>jersey-contracts</artifactId>
<version>0.0.1-SNAPSHOT</version>
<versioning>
<versions>
<version>0.0.1-SNAPSHOT</version>
</versions>
<lastUpdated>20160409062112</lastUpdated>
</versioning>
</metadata>

View File

@@ -1,18 +0,0 @@
/*
* 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.
*/
include ':fraudDetectionService'
include ':loanApplicationService'

View File

@@ -1,132 +0,0 @@
/*
* 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.
*/
buildscript {
repositories {
mavenCentral()
mavenLocal()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/release" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${bootVersion}")
}
}
ext {
restAssuredVersion = '3.0.7'
spockVersion = '1.0-groovy-2.4'
contractVerifierStubsBaseDirectory = 'src/test/resources/stubs'
}
group = 'org.springframework.cloud.testprojects'
subprojects {
apply plugin: 'groovy'
sourceCompatibility = 1.8
targetCompatibility = 1.8
repositories {
mavenCentral()
mavenLocal()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/release" }
}
dependencies {
testCompile("org.codehaus.groovy:groovy")
testCompile "org.spockframework:spock-core:$spockVersion"
testCompile("junit:junit:4.12")
testCompile "com.github.tomakehurst:wiremock:${wiremockVersion}"
testCompile "com.toomuchcoding.jsonassert:jsonassert:${jsonAssertVersion}"
testCompile "org.springframework.cloud:spring-cloud-contract-verifier:${verifierVersion}"
}
}
configure([project(':fraudDetectionService'), project(':loanApplicationService')]) {
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'spring-cloud-contract'
apply plugin: 'maven-publish'
ext {
contractsDir = file("mappings")
stubsOutputDirRoot = file("${project.buildDir}/production/${project.name}-stubs/")
}
contracts {
contractsMode = "REMOTE"
testFramework = 'Spock'
testMode = 'MockMvc'
baseClassForTests = 'org.springframework.cloud.MvcSpec'
contractsDslDir = file("${project.projectDir.absolutePath}/mappings/")
generatedTestSourcesDir = file("${project.buildDir}/generated-test-sources/")
stubsOutputDir = stubsOutputDirRoot
}
jar {
version = '0.0.1'
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web") {
exclude module: "spring-boot-starter-tomcat"
}
compile("org.springframework.boot:spring-boot-starter-jetty")
compile("org.springframework.boot:spring-boot-starter-actuator")
testRuntime("org.spockframework:spock-spring:$spockVersion") {
exclude(group: 'org.codehaus.groovy')
}
testCompile "org.mockito:mockito-core"
testCompile "org.springframework:spring-test"
testCompile "org.springframework.boot:spring-boot-test"
testCompile "io.rest-assured:rest-assured:$restAssuredVersion"
testCompile "io.rest-assured:spring-mock-mvc:$restAssuredVersion"
}
task cleanup(type: Delete) {
delete 'src/test/resources/mappings', 'src/test/resources/stubs'
}
clean.dependsOn('cleanup')
test {
testLogging {
exceptionFormat = 'full'
}
}
}
configure(project(':fraudDetectionService')) {
test.dependsOn('generateClientStubs')
}
configure(project(':loanApplicationService')) {
task copyCollaboratorStubs(type: Copy) {
File fraudBuildDir = project(':fraudDetectionService').buildDir
from(new File(fraudBuildDir, "/production/${project(':fraudDetectionService').name}-stubs/"))
into "src/test/resources/"
}
project.tasks.named("generateContractTests").get().dependsOn('copyCollaboratorStubs')
}

View File

@@ -1,46 +0,0 @@
/*
* 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.frauddetection.model;
import java.math.BigDecimal;
public class FraudCheck {
private String clientPesel;
private BigDecimal loanAmount;
public FraudCheck() {
}
public String getClientPesel() {
return this.clientPesel;
}
public void setClientPesel(String clientPesel) {
this.clientPesel = clientPesel;
}
public BigDecimal getLoanAmount() {
return this.loanAmount;
}
public void setLoanAmount(BigDecimal loanAmount) {
this.loanAmount = loanAmount;
}
}

View File

@@ -1,49 +0,0 @@
/*
* 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.frauddetection.model;
public class FraudCheckResult {
private FraudCheckStatus fraudCheckStatus;
private String rejectionReason;
public FraudCheckResult() {
}
public FraudCheckResult(FraudCheckStatus fraudCheckStatus, String rejectionReason) {
this.fraudCheckStatus = fraudCheckStatus;
this.rejectionReason = rejectionReason;
}
public FraudCheckStatus getFraudCheckStatus() {
return this.fraudCheckStatus;
}
public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
this.fraudCheckStatus = fraudCheckStatus;
}
public String getRejectionReason() {
return this.rejectionReason;
}
public void setRejectionReason(String rejectionReason) {
this.rejectionReason = rejectionReason;
}
}

View File

@@ -1,23 +0,0 @@
/*
* 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.frauddetection.model;
public enum FraudCheckStatus {
OK, FRAUD
}

View File

@@ -1,4 +0,0 @@
#WireMock password - https://wiremock.org/docs/running-standalone/
server.ssl.key-store-password=password
server.ssl.key-password=password
server.ssl.trust-store-password=password

View File

@@ -1,19 +0,0 @@
#
# 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.
#
wiremockVersion=2.24.1
jsonAssertVersion=0.4.13
verifierVersion=2.2.0.BUILD-SNAPSHOT
bootVersion=2.2.0.BUILD-SNAPSHOT

View File

@@ -1,5 +0,0 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -1,172 +0,0 @@
#!/usr/bin/env sh
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin, switch paths to Windows format before running java
if $cygwin ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=$((i+1))
done
case $i in
(0) set -- ;;
(1) set -- "$args0" ;;
(2) set -- "$args0" "$args1" ;;
(3) set -- "$args0" "$args1" "$args2" ;;
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=$(save "$@")
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
cd "$(dirname "$0")"
fi
exec "$JAVACMD" "$@"

View File

@@ -1,84 +0,0 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -1,83 +0,0 @@
/*
* 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.frauddetection;
import org.springframework.cloud.frauddetection.model.FraudCheckStatus;
import org.springframework.cloud.frauddetection.model.FraudServiceRequest;
import org.springframework.cloud.frauddetection.model.FraudServiceResponse;
import org.springframework.cloud.frauddetection.model.LoanApplication;
import org.springframework.cloud.frauddetection.model.LoanApplicationResult;
import org.springframework.cloud.frauddetection.model.LoanApplicationStatus;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;
@Service
public class LoanApplicationService {
private static final String FRAUD_SERVICE_JSON_VERSION_1 = "application/vnd.fraud.v1+json";
private final RestTemplate restTemplate;
private int port = 8080;
public LoanApplicationService() {
this.restTemplate = new RestTemplate();
}
public LoanApplicationResult loanApplication(LoanApplication loanApplication) {
FraudServiceRequest request = new FraudServiceRequest(loanApplication);
FraudServiceResponse response = sendRequestToFraudDetectionService(request);
return buildResponseFromFraudResult(response);
}
private FraudServiceResponse sendRequestToFraudDetectionService(
FraudServiceRequest request) {
HttpHeaders httpHeaders = new HttpHeaders();
httpHeaders.add(HttpHeaders.CONTENT_TYPE, FRAUD_SERVICE_JSON_VERSION_1);
ResponseEntity<FraudServiceResponse> response = this.restTemplate.exchange(
"http://localhost:" + this.port + "/fraudcheck", HttpMethod.PUT,
new HttpEntity<>(request, httpHeaders), FraudServiceResponse.class);
return response.getBody();
}
private LoanApplicationResult buildResponseFromFraudResult(
FraudServiceResponse response) {
LoanApplicationStatus applicationStatus = null;
if (FraudCheckStatus.OK == response.getFraudCheckStatus()) {
applicationStatus = LoanApplicationStatus.LOAN_APPLIED;
}
else if (FraudCheckStatus.FRAUD == response.getFraudCheckStatus()) {
applicationStatus = LoanApplicationStatus.LOAN_APPLICATION_REJECTED;
}
return new LoanApplicationResult(applicationStatus,
response.getRejectionReason());
}
public void setPort(int port) {
this.port = port;
}
}

View File

@@ -1,31 +0,0 @@
/*
* 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.frauddetection.model;
public class Client {
private String pesel;
public String getPesel() {
return this.pesel;
}
public void setPesel(String pesel) {
this.pesel = pesel;
}
}

View File

@@ -1,23 +0,0 @@
/*
* 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.frauddetection.model;
public enum FraudCheckStatus {
OK, FRAUD
}

View File

@@ -1,51 +0,0 @@
/*
* 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.frauddetection.model;
import java.math.BigDecimal;
public class FraudServiceRequest {
private String clientPesel;
private BigDecimal loanAmount;
public FraudServiceRequest() {
}
public FraudServiceRequest(LoanApplication loanApplication) {
this.clientPesel = loanApplication.getClient().getPesel();
this.loanAmount = loanApplication.getAmount();
}
public String getClientPesel() {
return this.clientPesel;
}
public void setClientPesel(String clientPesel) {
this.clientPesel = clientPesel;
}
public BigDecimal getLoanAmount() {
return this.loanAmount;
}
public void setLoanAmount(BigDecimal loanAmount) {
this.loanAmount = loanAmount;
}
}

View File

@@ -1,44 +0,0 @@
/*
* 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.frauddetection.model;
public class FraudServiceResponse {
private FraudCheckStatus fraudCheckStatus;
private String rejectionReason;
public FraudServiceResponse() {
}
public FraudCheckStatus getFraudCheckStatus() {
return this.fraudCheckStatus;
}
public void setFraudCheckStatus(FraudCheckStatus fraudCheckStatus) {
this.fraudCheckStatus = fraudCheckStatus;
}
public String getRejectionReason() {
return this.rejectionReason;
}
public void setRejectionReason(String rejectionReason) {
this.rejectionReason = rejectionReason;
}
}

View File

@@ -1,53 +0,0 @@
/*
* 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.frauddetection.model;
import java.math.BigDecimal;
public class LoanApplication {
private Client client;
private BigDecimal amount;
private String loanApplicationId;
public Client getClient() {
return this.client;
}
public void setClient(Client client) {
this.client = client;
}
public BigDecimal getAmount() {
return this.amount;
}
public void setAmount(BigDecimal amount) {
this.amount = amount;
}
public String getLoanApplicationId() {
return this.loanApplicationId;
}
public void setLoanApplicationId(String loanApplicationId) {
this.loanApplicationId = loanApplicationId;
}
}

View File

@@ -1,50 +0,0 @@
/*
* 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.frauddetection.model;
public class LoanApplicationResult {
private LoanApplicationStatus loanApplicationStatus;
private String rejectionReason;
public LoanApplicationResult() {
}
public LoanApplicationResult(LoanApplicationStatus loanApplicationStatus,
String rejectionReason) {
this.loanApplicationStatus = loanApplicationStatus;
this.rejectionReason = rejectionReason;
}
public LoanApplicationStatus getLoanApplicationStatus() {
return this.loanApplicationStatus;
}
public void setLoanApplicationStatus(LoanApplicationStatus loanApplicationStatus) {
this.loanApplicationStatus = loanApplicationStatus;
}
public String getRejectionReason() {
return this.rejectionReason;
}
public void setRejectionReason(String rejectionReason) {
this.rejectionReason = rejectionReason;
}
}

View File

@@ -1,23 +0,0 @@
/*
* 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.frauddetection.model;
public enum LoanApplicationStatus {
LOAN_APPLIED, LOAN_APPLICATION_REJECTED
}

View File

@@ -1,72 +0,0 @@
/*
* 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
import com.github.tomakehurst.wiremock.junit.WireMockClassRule
import org.junit.ClassRule
import spock.lang.Shared
import spock.lang.Specification
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootContextLoader
import org.springframework.cloud.frauddetection.Application
import org.springframework.cloud.frauddetection.LoanApplicationService
import org.springframework.cloud.frauddetection.model.Client
import org.springframework.cloud.frauddetection.model.LoanApplication
import org.springframework.cloud.frauddetection.model.LoanApplicationResult
import org.springframework.cloud.frauddetection.model.LoanApplicationStatus
import org.springframework.test.context.ContextConfiguration
@ContextConfiguration(loader = SpringBootContextLoader, classes = Application)
class LoanApplicationServiceSpec extends Specification {
public static int port = org.springframework.util.SocketUtils.findAvailableTcpPort()
@ClassRule
@Shared
WireMockClassRule wireMockRule = new WireMockClassRule(port)
@Autowired
LoanApplicationService sut
def setup() {
sut.port = port
}
def 'should successfully apply for loan'() {
given:
LoanApplication application =
new LoanApplication(client: new Client(pesel: '1234567890'), amount: 123.123)
when:
LoanApplicationResult loanApplication = sut.loanApplication(application)
then:
loanApplication.loanApplicationStatus == LoanApplicationStatus.LOAN_APPLIED
loanApplication.rejectionReason == null
}
def 'should be rejected due to abnormal loan amount'() {
given:
LoanApplication application =
new LoanApplication(client: new Client(pesel: '1234567890'), amount: 99_999)
when:
LoanApplicationResult loanApplication = sut.loanApplication(application)
then:
loanApplication.loanApplicationStatus == LoanApplicationStatus.LOAN_APPLICATION_REJECTED
loanApplication.rejectionReason == 'Amount too high'
}
}

View File

@@ -1,19 +0,0 @@
/*
* 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.
*/
include ':fraudDetectionService'
include ':loanApplicationService'

View File

@@ -14,18 +14,9 @@
* limitations under the License.
*/
buildscript {
repositories {
mavenCentral()
mavenLocal()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/release" }
}
dependencies {
classpath("org.springframework.boot:spring-boot-gradle-plugin:${bootVersion}")
}
plugins {
id("org.springframework.boot") apply false
id("org.springframework.cloud.contract") apply false
}
ext {
@@ -69,7 +60,7 @@ subprojects {
configure([project(':fraudDetectionService'), project(':loanApplicationService')]) {
apply plugin: 'org.springframework.boot'
apply plugin: 'io.spring.dependency-management'
apply plugin: 'spring-cloud-contract'
apply plugin: 'org.springframework.cloud.contract'
// tag::jar_setup[]
ext {

View File

@@ -14,6 +14,24 @@
* limitations under the License.
*/
pluginManagement {
repositories {
mavenCentral()
mavenLocal()
maven { url "https://repo.spring.io/snapshot" }
maven { url "https://repo.spring.io/milestone" }
maven { url "https://repo.spring.io/release" }
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.springframework.boot") {
useModule("org.springframework.boot:spring-boot-gradle-plugin:${bootVersion}")
} else if (requested.id.id == "org.springframework.cloud.contract") {
useModule("org.springframework.cloud:spring-cloud-contract-gradle-plugin:${verifierVersion}")
}
}
}
}
include ':fraudDetectionService'
include ':loanApplicationService'

View File

@@ -0,0 +1,137 @@
/*
* 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.
*/
import org.springframework.cloud.contract.stubrunner.spring.StubRunnerProperties
import org.springframework.cloud.contract.verifier.config.TestFramework
import org.springframework.cloud.contract.verifier.config.TestMode
import org.springframework.cloud.contract.verifier.plugin.ContractVerifierExtension
plugins {
groovy
id("org.springframework.boot") apply false
id("org.springframework.cloud.contract") apply false
}
val restAssuredVersion by extra("3.0.7")
val spockVersion by extra("1.0-groovy-2.4")
val wiremockVersion: String by extra
val jsonAssertVersion: String by extra
val verifierVersion: String by extra
val contractVerifierStubsBaseDirectory by extra("src/test/resources/stubs")
group = "org.springframework.cloud.testprojects"
subprojects {
apply(plugin = "groovy")
java {
sourceCompatibility = JavaVersion.VERSION_1_8
targetCompatibility = JavaVersion.VERSION_1_8
}
repositories {
mavenCentral()
mavenLocal()
maven(url = "https://repo.spring.io/snapshot")
maven(url = "https://repo.spring.io/milestone")
maven(url = "https://repo.spring.io/release")
}
dependencies {
testCompile("org.codehaus.groovy:groovy")
testCompile("org.spockframework:spock-core:$spockVersion")
testCompile("junit:junit:4.12")
testCompile("com.github.tomakehurst:wiremock:$wiremockVersion")
testCompile("com.toomuchcoding.jsonassert:jsonassert:$jsonAssertVersion")
testCompile("org.springframework.cloud:spring-cloud-contract-verifier:$verifierVersion")
}
}
configure(listOf(project(":fraudDetectionService"), project(":loanApplicationService"))) {
apply(plugin = "org.springframework.boot")
apply(plugin = "io.spring.dependency-management")
apply(plugin = "org.springframework.cloud.contract")
apply(plugin = "maven-publish")
configure<ContractVerifierExtension> {
contractsMode.set(StubRunnerProperties.StubsMode.REMOTE)
testFramework.set(TestFramework.SPOCK)
testMode.set(TestMode.MOCKMVC)
baseClassForTests.set("org.springframework.cloud.MvcSpec")
contractsDslDir.set(file("${project.projectDir}/mappings/"))
generatedTestSourcesDir.set(file("${project.buildDir}/generated-test-sources/"))
stubsOutputDir.set(file("${project.buildDir}/production/${project.name}-stubs/"))
}
dependencies {
compile("org.springframework.boot:spring-boot-starter-web") {
exclude(module = "spring-boot-starter-tomcat")
}
compile("org.springframework.boot:spring-boot-starter-jetty")
compile("org.springframework.boot:spring-boot-starter-actuator")
testRuntime("org.spockframework:spock-spring:$spockVersion") {
exclude(group = "org.codehaus.groovy")
}
testCompile("org.mockito:mockito-core")
testCompile("org.springframework:spring-test")
testCompile("org.springframework.boot:spring-boot-test")
testCompile("io.rest-assured:rest-assured:$restAssuredVersion")
testCompile("io.rest-assured:spring-mock-mvc:$restAssuredVersion")
}
tasks {
jar {
version = "0.0.1"
}
test {
testLogging.showExceptions = true
}
val cleanup by registering(Delete::class) {
delete("src/test/resources/mappings", "src/test/resources/stubs")
}
clean {
dependsOn(cleanup)
}
}
}
configure(listOf(project(":fraudDetectionService"))) {
tasks {
test {
dependsOn("generateClientStubs")
}
}
}
configure(listOf(project(":loanApplicationService"))) {
tasks {
val copyCollaboratorStubs by registering(Copy::class) {
val fraudDetectionService = project(":fraudDetectionService")
from(file("${fraudDetectionService.buildDir}/production/${fraudDetectionService.name}-stubs"))
into("src/test/resources/mappings")
}
val generateContractTests by existing
generateContractTests {
dependsOn(copyCollaboratorStubs)
}
}
}

View File

@@ -1,84 +1,84 @@
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

View File

@@ -20,6 +20,7 @@ import com.github.tomakehurst.wiremock.junit.WireMockClassRule
import org.junit.ClassRule
import spock.lang.Shared
import spock.lang.Specification
import spock.lang.Stepwise
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.boot.test.context.SpringBootContextLoader
@@ -32,6 +33,7 @@ import org.springframework.cloud.frauddetection.model.LoanApplicationStatus
import org.springframework.test.context.ContextConfiguration
@ContextConfiguration(loader = SpringBootContextLoader, classes = Application)
@Stepwise
class LoanApplicationServiceSpec extends Specification {
public static int port = org.springframework.util.SocketUtils.findAvailableTcpPort()

View File

@@ -0,0 +1,39 @@
/*
* 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.
*/
pluginManagement {
repositories {
mavenCentral()
mavenLocal()
maven(url = "https://repo.spring.io/snapshot")
maven(url = "https://repo.spring.io/milestone")
maven(url = "https://repo.spring.io/release")
}
resolutionStrategy {
eachPlugin {
if (requested.id.id == "org.springframework.boot") {
val bootVersion: String by extra
useModule("org.springframework.boot:spring-boot-gradle-plugin:$bootVersion")
} else if (requested.id.id == "org.springframework.cloud.contract") {
val verifierVersion: String by extra
useModule("org.springframework.cloud:spring-cloud-contract-gradle-plugin:$verifierVersion")
}
}
}
}
include(":fraudDetectionService")
include(":loanApplicationService")