Gradle 專案
先決條件
要將 Spring Cloud Contract Verifier 與 WireMock 結合使用,您必須使用 Gradle 或 Maven 外掛。
如果您想在專案中使用 Spock,則必須單獨新增 spock-core 和 spock-spring 模組。有關更多資訊,請參閱 Spock 的文件。 |
新增帶依賴項的 Gradle 外掛
要新增帶依賴項的 Gradle 外掛,您可以使用類似於以下的程式碼
- 外掛 DSL GA 版本
-
// 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 外掛設定建立以下 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
配置外掛
要更改預設配置,您可以向 Gradle 配置新增一個 contracts 片段,如以下清單所示
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 直接提供的原生機制來定製現有任務,如下所示
為了舉例說明,我們希望將 git.properties 檔案新增到 verifierStubsJar 中。 |
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:指定包含使用 GroovyDSL 編寫的契約的目錄。預設情況下,其值為$projectDir/src/contractTest/resources/contracts。 -
generatedTestSourcesDir:指定應放置從 Groovy DSL 生成的測試的測試源目錄。(已棄用) -
generatedTestJavaSourcesDir:指定應放置從 Groovy DSL 生成的 Java/JUnit 測試的測試源目錄。預設情況下,其值為$buildDir/generated-tes-sources/contractTest/java。 -
generatedTestGroovySourcesDir:指定應放置從 Groovy DSL 生成的 Groovy/Spock 測試的測試源目錄。預設情況下,其值為$buildDir/generated-test-sources/contractTest/groovy。 -
generatedTestResourcesDir:指定應放置從 Groovy DSL 生成的測試所使用的資源的測試資源目錄。預設情況下,其值為$buildDir/generated-test-resources/contractTest。 -
stubsOutputDir:指定應放置從 Groovy DSL 生成的 WireMock 存根的目錄。 -
testFramework:指定要使用的目標測試框架。目前支援 Spock、JUnit 4 (TestFramework.JUNIT) 和 JUnit 5,其中 JUnit 4 是預設框架。 -
contractsProperties:包含要傳遞給 Spring Cloud Contract 元件的屬性的對映。這些屬性可能由(例如)內建或自定義存根下載器使用。 -
sourceSet:儲存契約的源集。如果未提供,則假定為contractTest(例如,JUnit 的project.sourceSets.contractTest.java或 Spock 的project.sourceSets.contractTest.groovy)。
當您想指定包含契約的 JAR 的位置時,可以使用以下屬性
-
contractDependency:指定提供groupid:artifactid:version:classifier座標的依賴項。您可以使用contractDependency閉包進行設定。 -
contractsPath:指定 jar 的路徑。如果下載了契約依賴項,則路徑預設為groupid/artifactid,其中groupid以斜槓分隔。否則,它會在提供的目錄下掃描契約。 -
contractsMode:指定下載契約的模式(JAR 是否可離線、遠端等)。 -
deleteStubsAfterTest:如果設定為false,則不會從臨時目錄中刪除任何下載的契約。 -
failOnNoContracts:啟用後,如果未找到任何契約,則會丟擲異常。預設為true。 -
failOnInProgress:如果設定為true,則如果發現任何正在進行的契約,它們將中斷構建。在生產者端,您需要明確表示您有正在進行的契約,並考慮您可能會在消費者端導致假陽性測試結果。預設為true。
還有一個 contractRepository { … } 閉包,其中包含以下屬性
-
repositoryUrl:包含契約定義的倉庫的 URL -
username:倉庫使用者名稱 -
password:倉庫密碼 -
proxyPort:代理埠 -
proxyHost:代理主機 -
cacheDownloadedContracts:如果設定為true,則快取非快照契約工件下載的資料夾。預設為true。
您還可以在外掛中啟用以下實驗性功能
-
convertToYaml:將所有 DSL 轉換為宣告性 YAML 格式。當您在 Groovy DSL 中使用外部庫時,這會非常有用。透過啟用此功能(將其設定為true),您無需在消費者端新增庫依賴項。 -
assertJsonSize:您可以檢查生成測試中 JSON 陣列的大小。此功能預設停用。
所有測試的單一基類
在 MockMvc(預設)中使用 Spring Cloud Contract Verifier 時,您需要為所有生成的驗收測試建立一個基本規範。在此類中,您需要指向應驗證的端點。以下示例顯示瞭如何執行此操作
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 假定在 com.example.base 包下有一個 BarBazBase 類。換句話說,系統會取包的最後兩個部分(如果存在),並形成一個帶有 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 包含在您自己的釋出之一中。
將存根推送到 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
必須設定 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 伺服器處理。