|
请使用 spring-cloud-contract 5.0.2 获取最新稳定版本! |
项目 Gradle
前置条件
要使用 Spring Cloud Contract Verifier 与 WireMock,您必须使用 Gradle 或 Maven 插件。
如果要在项目中使用 Spock,必须分别添加spock-core和spock-spring模块。有关更多信息,请参阅Spock的文档。 |
添加Gradle插件和依赖
要添加带有依赖项的 Gradle 插件,可以使用类似的代码:
- 插件DSLGA版本
-
// build.gradle plugins { id "groovy" // this will work only for GA versions of Spring Cloud Contract id "org.springframework.cloud.contract" version "$\{GAVerifierVersion}" } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:$\{GAVerifierVersion}" } } dependencies { testImplementation "org.apache.groovy:groovy-all:$\{groovyVersion}" // example with adding Spock core and Spock Spring testImplementation "org.spockframework:spock-core:$\{spockVersion}" testImplementation "org.spockframework:spock-spring:$\{spockVersion}" testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-verifier' } - 插件DSL非GA版本
-
// settings.gradle pluginManagement { plugins { id "org.springframework.cloud.contract" version "$\{verifierVersion}" } repositories { // to pick from local .m2 mavenLocal() // for snapshots maven { url "https://repo.spring.io/snapshot" } // for milestones maven { url "https://repo.spring.io/milestone" } // for GA versions gradlePluginPortal() } } // build.gradle plugins { id "groovy" id "org.springframework.cloud.contract" } dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:$\{verifierVersion}" } } dependencies { testImplementation "org.apache.groovy:groovy-all:$\{groovyVersion}" // example with adding Spock core and Spock Spring testImplementation "org.spockframework:spock-core:$\{spockVersion}" testImplementation "org.spockframework:spock-spring:$\{spockVersion}" testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-verifier' } - 无插件应用程序
-
// build.gradle buildscript { repositories { mavenCentral() } dependencies { classpath "org.springframework.boot:spring-boot-gradle-plugin:$\{springboot_version}" classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:$\{verifier_version}" // here you can also pass additional dependencies such as Kotlin spec e.g.: // classpath "org.springframework.cloud:spring-cloud-contract-spec-kotlin:$\{verifier_version}" } } apply plugin: 'groovy' apply plugin: 'org.springframework.cloud.contract' dependencyManagement { imports { mavenBom "org.springframework.cloud:spring-cloud-contract-dependencies:$\{verifier_version}" } } dependencies { testImplementation "org.apache.groovy:groovy-all:$\{groovyVersion}" // example with adding Spock core and Spock Spring testImplementation "org.spockframework:spock-core:$\{spockVersion}" testImplementation "org.spockframework:spock-spring:$\{spockVersion}" testImplementation 'org.springframework.cloud:spring-cloud-starter-contract-verifier' }
Gradle 和 Rest Assured 2.0
默认情况下,Rest Assured 3.x 被添加到类路径。但是,要使用 Rest Assured 2.x,也可以代替它,如下面的清单所示:
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "org.springframework.boot:spring-boot-gradle-plugin:$\{springboot_version}"
classpath "org.springframework.cloud:spring-cloud-contract-gradle-plugin:$\{verifier_version}"
}
}
dependencies {
// all dependencies
// you can exclude rest-assured from spring-cloud-contract-verifier
testCompile "com.jayway.restassured:rest-assured:2.5.0"
testCompile "com.jayway.restassured:spring-mock-mvc:2.5.0"
}
这样,插件就能自动识别出 Rest Assured 2.x 已存在于类路径中,并据此相应地修改导入语句。
添加占位符
默认情况下,Spring Cloud Contract Verifier 会在
src/contractTest/resources/contracts 目录中查找存根。为过渡目的,插件
还会在 src/test/resources/contracts 目录中查找合同,但是,自 Spring Cloud Contract 3.0.0 起该目录已弃用。
还应该注意,使用这个新的 Gradle 源集,您也应该将任何在您的合同测试中使用的基类迁移到src/contractTest/{language},其中{language}应根据您的用途替换为 Java 或 Groovy。
存放桩定义的目录被视为类名,每个桩定义被视为单个测试。Spring Cloud Contract Verifier 假设它至少包含一个级别的目录,这些目录将用作测试类名。如果存在多级嵌套目录,除了最后一级之外的所有目录都将用作包名。请考虑以下结构:
src/contractTest/resources/contracts/myservice/shouldCreateUser.groovy
src/contractTest/resources/contracts/myservice/shouldReturnUser.groovy
根据前述结构,Spring Cloud Contract Verifier 会创建一个名为
defaultBasePackage.MyService 的测试类,包含两个方法:
-
shouldCreateUser() -
shouldReturnUser()
默认设置
默认的Gradle Plugin设置会创建以下构建中的Gradle部分(伪代码):
contracts {
testFramework ='JUNIT'
testMode = 'MockMvc'
generatedTestJavaSourcesDir = project.file("$\{project.buildDir}/generated-test-sources/contractTest/java")
generatedTestGroovySourcesDir = project.file("$\{project.buildDir}/generated-test-sources/contractTest/groovy")
generatedTestResourcesDir = project.file("$\{project.buildDir}/generated-test-resources/contracts")
contractsDslDir = project.file("$\{project.projectDir}/src/contractTest/resources/contracts")
basePackageForTests = 'org.springframework.cloud.verifier.tests'
stubsOutputDir = project.file("$\{project.buildDir}/stubs")
sourceSet = null
}
def verifierStubsJar = tasks.register(type: Jar, name: 'verifierStubsJar', dependsOn: 'generateClientStubs') {
baseName = project.name
classifier = contracts.stubsSuffix
from contractVerifier.stubsOutputDir
}
def copyContracts = tasks.register(type: Copy, name: 'copyContracts') {
from contracts.contractsDslDir
into contracts.stubsOutputDir
}
verifierStubsJar.dependsOn copyContracts
配置插件
要更改默认配置,可以将contracts代码段添加到Gradle配置中,如下面的清单所示:
contracts {
testMode = 'MockMvc'
baseClassForTests = 'org.mycompany.tests'
generatedTestJavaSourcesDir = project.file('src/generatedContract')
}
要从远程源下载合约,可以按需使用以下代码段:
contracts {
// If your contracts exist in a JAR archive published to a Maven repository
contractDependency {
stringNotation = ''
// OR
groupId = ''
artifactId = ''
version = ''
classifier = ''
}
// If your contracts exist in a Git SCM repository
contractRepository {
repositoryUrl = ''
// username = ''
// password = ''
}
// controls the nested location to find the contracts in either the JAR or Git SCM source
contractsPath = ''
}
由于我们正在使用 Gradle 的 Jar 打包任务,因此您可能希望利用几个选项和功能来进一步扩展由 verifierStubsJar 创建的内容。为此,您将像这样直接使用 Gradle 提供的自定义现有任务的本机机制:
| 为了示例,我们希望向添加一个文件。 |
verifierStubsJar {
from("$\{buildDir}/resources/main/") {
include("git.properties")
}
}
还应注意,从 3.0.0 版开始,默认发布已被禁用。这意味着您可以创建任何命名的 jar 并像以前一样通过 Gradle 配置选项将其发布。这意味着您可以构建一个按照您的意愿定制的 jar 文件,并发布该文件以完全控制 jar 的布局和内容。
配置选项
-
testMode: 定义接受测试的模式。默认情况下,模式为 MockMvc,它基于 Spring 的 MockMvc。也可以将其更改为 WebTestClient、JaxRsClient 或 Explicit(用于实际的 HTTP 调用)。 -
imports: 创建一个数组,其中包含应包含在生成的测试中的导入(例如,['org.myorg.Matchers'])。默认情况下,它创建一个空数组。 -
staticImports: 创建一个包含应包含在生成测试中(例如,['org.myorg.Matchers.*'])的静态导入的数组。默认情况下,它创建一个空数组。 -
basePackageForTests: 指定所有生成测试的基本包。如果未设置, 值从baseClassForTests和packageWithBaseClasses中选择。如果这两个值均未设置,则值为org.springframework.cloud.contract.verifier.tests。 -
baseClassForTests: 创建所有生成测试的基础类。默认情况下,如果您 使用 Spock 类,则该类是spock.lang.Specification。 -
packageWithBaseClasses: 定义了一个包,其中所有基本类都位于该包中。此设置优先于baseClassForTests。 -
baseClassMappings: 明确地将契约包映射到基础类的完全限定名。此设置对packageWithBaseClasses和baseClassForTests具有优先级。 -
ignoredFiles: 使用一个Antmatcher来允许定义跳过处理的存根文件。默认情况下,它是一个空数组。 -
contractsDslDir: 指定包含使用 Groovy DSL 编写的契约的目录。默认值为$projectDir/src/contractTest/resources/contracts。 -
generatedTestSourcesDir: 指定测试源目录,测试生成的 Groovy DSL 应该被放在该目录下。(已废弃) -
generatedTestJavaSourcesDir: 指定测试源目录,Groovy DSL 生成的 Java/JUnit 测试应放置在此处。默认值为$buildDir/generated-tes-sources/contractTest/java。 -
generatedTestGroovySourcesDir: 指定测试源目录,Groovy/Spock 测试生成的 Groovy DSL 应该放在该目录。默认值为$buildDir/generated-test-sources/contractTest/groovy。 -
generatedTestResourcesDir: 指定测试资源目录,用于放置从 Groovy DSL 生成的测试使用的资源。默认值为$buildDir/generated-test-resources/contractTest。 -
stubsOutputDir: 指定生成的 WireMock 存档从 Groovy DSL 生成的位置。 -
testFramework: 指定要使用的目标测试框架。目前支持 Spock、JUnit 4 (TestFramework.JUNIT) 和 JUnit 5,其中 JUnit 4 是默认框架。 -
contractsProperties: 一个包含要传递给 Spring Cloud Contract 组件的属性的映射。这些属性可能被(例如)内置或自定义存档下载器所使用。 -
0: 源集,存储合约的地方。如果没有提供,将假设为1(例如,2用于 JUnit 或者3用于 Spock)。
你可以在指定包含合同的JAR文件位置时使用以下属性:
-
contractDependency: Specifies the Dependency that providesgroupid:artifactid:version:classifiercoordinates. You can use thecontractDependencyclosure to set it up. -
contractsPath: 指定 jar 的路径。如果合同依赖项已 下载,该路径默认为groupid/artifactid,其中groupid是斜杠分隔符。否则,它扫描提供的目录下的合同。 -
contractsMode: 指定下载合同的模式(是否 JAR 可以离线使用、远程使用等)。 -
deleteStubsAfterTest: 如果设置为false,则不会从临时目录中删除任何下载的 合同。 -
failOnNoContracts: 当启用时,如果没有找到合同将抛出异常。默认值为true。 -
failOnInProgress:如果设置为true,那么,如果有发现正在进行的合约,就会中断构建。在生产者端,您需要明确表示您有进行中的合约,并考虑到您可能会在消费者端引起测试结果的误报。默认值为true。
也存在一个包含以下属性的0闭包
-
repositoryUrl: 用于存储合同定义的存储库的URL -
username: The repository username -
password: The repository password -
proxyPort: 代理服务器的端口 -
proxyHost: 代理的主机 -
cacheDownloadedContracts: 如果设置为true,则缓存非快照合同工件下载的文件夹。默认值为true。
您还可以在插件中打开以下实验性功能:
-
convertToYaml: 将所有 DSL 转换为声明性 YAML 格式。这在您的 Groovy DSL 中使用外部库时可能非常有用。通过将此功能打开(设置为true),您无需在消费端添加库依赖项。 -
assertJsonSize: 可在生成的测试中检查 JSON 数组的大小。此功能默认已禁用。
继承所有测试的基类
在使用 Spring Cloud Contract Verifier in MockMvc(默认)时,您需要为所有生成的接收测试创建一个基本规范。 在此类中,您需要指向要验证的端点。 以下示例说明了如何做到这一点:
abstract class BaseMockMvcSpec extends Specification {
def setup() {
RestAssuredMockMvc.standaloneSetup(new PairIdController())
}
void isProperCorrelationId(Integer correlationId) {
assert correlationId == 123456
}
void isEmpty(String value) {
assert value == null
}
}
如果您使用Explicit模式,可以使用基类来初始化整个被测试的应用程序,就像您可能在常规集成测试中看到的那样。如果您使用JAXRSCLIENT模式,这个基类也应该包含一个protected WebTarget webTarget字段。现在,测试JAX-RS API的唯一方法是启动Web服务器。
不同基类用于合同
如果基类在合同之间有所不同,您可以告诉Spring Cloud Contract插件哪个类应该由自动生成的测试来扩展。您有两个选项:
-
遵循约定,提供
packageWithBaseClasses -
提供显式映射,使用
baseClassMappings
通过约定
约定是这样的,如果你有(例如)一个合同在src/contractTest/resources/contract/foo/bar/baz/并且设置值的packageWithBaseClasses属性为com.example.base,那么Spring Cloud Contract Verifier认为存在一个BarBazBase类下com.example.base包。换句话说,系统采用包的最后两部分,如果它们存在,并形成带有Base后缀的类。此规则优先于baseClassForTests。
通过映射
您可以手动映射合同包的正则表达式到匹配合同的基本类的完全限定名称。您必须提供一个名为baseClassMappings的列表,它由包含baseClassMapping对象的集合组成,这些对象采用contractPackageRegex到baseClassFQN个映射。
假设您在以下目录中拥有合同:
-
src/contractTest/resources/contract/com/ -
src/contractTest/resources/contract/foo/
通过提供baseClassForTests,如果映射未成功,我们会有一个后备方案。(您还可以作为后备方案提供packageWithBaseClasses。)这样,从src/contractTest/resources/contract/com/合约生成的测试扩展com.example.ComBase,而其余测试则扩展com.example.FooBase。
发布到项目存储库的存档文件
如果您使用二进制工件存储库来保存桩文件,您将需要为 Gradle 配置发布部分以包含 verifierStubsJar。为此,您可以使用下面的示例配置。
apply plugin: 'maven-publish'
publishing {
publications {
maven(MavenPublication) {
// other configuration
artifact verifierStubsJar
}
}
}
从 3.0.0 版开始,内部存档发布已弃用且默认情况下已禁用。建议使用其中一个自己的发布版本包含verifierStubsJar。
将Mock对象推送到SCM
如果使用SCM存储库来保存合同和存根,您可能希望自动化将存根推送到存储库的步骤。为此,可以调用pushStubsToScm任务,通过运行以下命令:
$ ./gradlew pushStubsToScm
在 使用 SCM 存档下载器 中,您可以找到所有可能传递给您的配置选项。您可以在 contractsProperties 字段中(例如,contracts { contractsProperties = [foo:"bar"] }),通过 contractsProperties 方法中(例如,contracts { contractsProperties([foo:"bar"]) })或通过系统属性或环境变量传递。
Spring Cloud Contract Verifier 在消费者端
在使用服务中,您需要以与提供程序的情况完全相同的方式配置Spring Cloud Contract Verifier插件。如果您不想使用Stub Runner,您需要复制存储在src/contractTest/resources/contracts中的合约,并通过使用以下命令生成WireMock JSON存根:
./gradlew generateClientStubs
The stubsOutputDir 选项必须设置以便存根生成能够工作。 |
当存在时,您可以在自动化测试中使用JSON存档来使用服务。下面的例子说明了如何做到这一点:
@ContextConfiguration(loader == SpringApplicationContextLoader, classes == Application)
class LoanApplicationServiceSpec extends Specification {
@ClassRule
@Shared
WireMockClassRule wireMockRule == new WireMockClassRule()
@Autowired
LoanApplicationService sut
def 'should successfully apply for loan'() {
given:
LoanApplication application =
new LoanApplication(client: new Client(clientPesel: '12345678901'), amount: 123.123)
when:
LoanApplicationResult loanApplication == sut.loanApplication(application)
then:
loanApplication.loanApplicationStatus == LoanApplicationStatus.LOAN_APPLIED
loanApplication.rejectionReason == null
}
}
在前述示例中,LoanApplication 会调用 FraudDetection 服务。
此请求由一个通过 Spring Cloud Contract Verifier 生成的存根配置的 WireMock 服务器处理。