添加maven插件
添加Spring Cloud Contract BOM
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-dependencies</artifactId>
<version>${spring-cloud-dependencies.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
接下來,Spring Cloud Contract Verifier Maven插件
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<packageWithBaseClasses>com.example.fraud</packageWithBaseClasses>
</configuration>
</plugin>
您可以在Spring Cloud Contract Maven插件文檔中閱讀更多內(nèi)容
Maven的快照版本
對于快照/里程碑版本,您必須將以下部分添加到您的pom.xml
<repositories>
<repository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</repository>
<repository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-snapshots</id>
<name>Spring Snapshots</name>
<url>https://repo.spring.io/snapshot</url>
<snapshots>
<enabled>true</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-milestones</id>
<name>Spring Milestones</name>
<url>https://repo.spring.io/milestone</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
<pluginRepository>
<id>spring-releases</id>
<name>Spring Releases</name>
<url>https://repo.spring.io/release</url>
<snapshots>
<enabled>false</enabled>
</snapshots>
</pluginRepository>
</pluginRepositories>
添加存根
默認(rèn)情況下Spring Cloud Contract驗證器正在src/test/resources/contracts目錄中查找存根。包含存根定義的目錄被視為一個類名稱,每個存根定義被視為單個測試。我們假設(shè)它至少包含一個用作測試類名稱的目錄。如果有多個級別的嵌套目錄,除了最后一個級別將被用作包名稱。所以具有以下結(jié)構(gòu)
src/test/resources/contracts/myservice/shouldCreateUser.groovy
src/test/resources/contracts/myservice/shouldReturnUser.groovy
Spring Cloud Contract驗證者將使用兩種方法創(chuàng)建測試類defaultBasePackage.MyService - shouldCreateUser() - shouldReturnUser()
運行插件
插件目標(biāo)generateTests被分配為階段generate-test-sources。只要您希望它成為構(gòu)建過程的一部分,您就無所事事。如果您只想生成測試,請調(diào)用generateTests目標(biāo)。
配置插件
要更改默認(rèn)配置,只需將configuration部分添加到插件定義或execution定義。
<plugin>
? ? <groupId>org.springframework.cloud</groupId>
? ? <artifactId>spring-cloud-contract-maven-plugin</artifactId>
? ? <executions>
? ? ? ? <execution>
? ? ? ? ? ? <goals>
? ? ? ? ? ? ? ? <goal>convert</goal>
? ? ? ? ? ? ? ? <goal>generateStubs</goal>
? ? ? ? ? ? ? ? <goal>generateTests</goal>
? ? ? ? ? ? </goals>
? ? ? ? </execution>
? ? </executions>
? ? <configuration>
? ? ? ? <basePackageForTests>org.springframework.cloud.verifier.twitter.place</basePackageForTests>
? ? ? ? <baseClassForTests>org.springframework.cloud.verifier.twitter.place.BaseMockMvcSpec</baseClassForTests>
? ? </configuration>
</plugin>
重要配置選項
? ? testMode - 定義接受測試的模式。默認(rèn)MockMvc,它基于Spring的MockMvc。對于真正的HTTP呼叫,它也可以更改為JaxRsClient或Explicit。
? ? basePackageForTests - 為所有生成的測試指定基礎(chǔ)包。默認(rèn)設(shè)置為org.springframework.cloud.verifier.tests。
? ? ruleClassForTests - 指定應(yīng)該添加到生成的測試類的規(guī)則。
? ? baseClassForTests - 生成測試的基類。如果使用Spock測試,默認(rèn)為spock.lang.Specification。
? ? contractDir - 包含使用GroovyDSL編寫的合同的目錄。默認(rèn)/src/test/resources/contracts。
? ? testFramework - 要使用的目標(biāo)測試框架; JUnit作為默認(rèn)框架,目前支持Spock和JUnit
? ? packageWithBaseClasses - 而不是為基類提供固定值,您可以提供一個所有基類放置的包。約定是這樣的,如果你有合同src/test/resources/contract/foo/bar/baz/,并提供這個屬性的值到com.example.base,那么我們將假設(shè)com.example.base包含com.example.base類。優(yōu)先于baseClassForTests
? ? baseClassMappings - 您必須提供contractPackageRegex的基類映射列表,該列表根據(jù)合同所在的包進(jìn)行檢查,并且baseClassFQN映射到匹配合同的基類的完全限定名稱。如果您有合同src/test/resources/contract/foo/bar/baz/并映射了屬性.*→com.example.base.BaseClass,則從這些合同生成的測試類將擴展com.example.base.BaseClass。優(yōu)先于packageWithBaseClasses 和baseClassForTests。
如果要從Maven存儲庫中下載合同定義,可以使用
? ? contractsRepositoryUrl - 具有合同的工件的repo的URL(如果沒有提供)應(yīng)使用當(dāng)前的Maven
? ? contractDependency - 包含所有打包合同的合同依賴關(guān)系
? ? contractPath - 通過打包合同在JAR中具體合同的路徑。默認(rèn)為groupid/artifactid,其中g(shù)ropuid被斜杠分隔。
? ? contractWorkOffline - 如果依賴關(guān)系應(yīng)該被下載,或者本地Maven只能被重用
有關(guān)完整信息,請參閱插件文檔
所有測試的單一基類
在默認(rèn)的MockMvc中使用Spring Cloud Contract驗證器時,您需要為所有生成的驗收測試創(chuàng)建一個基本規(guī)范。在這個類中,您需要指向應(yīng)驗證的端點。
package org.mycompany.tests
import org.mycompany.ExampleSpringController
import com.jayway.restassured.module.mockmvc.RestAssuredMockMvc
import spock.lang.Specification
class? MvcSpec extends Specification {
? def setup() {
? RestAssuredMockMvc.standaloneSetup(new ExampleSpringController())
? }
}
在使用Explicit模式的情況下,您可以像常規(guī)集成測試一樣使用基類來初始化整個測試的應(yīng)用程序。在JAXRSCLIENT模式的情況下,這個基類也應(yīng)該包含protected WebTarget webTarget字段,現(xiàn)在測試JAX-RS API的唯一選項是啟動Web服務(wù)器。
不同的基礎(chǔ)類別的合同
如果您的基類在合同之間不同,您可以告訴Spring Cloud Contract插件哪個類應(yīng)該由自動生成測試擴展。你有兩個選擇:
? ? 遵循約定,提供packageWithBaseClasses
? ? 通過baseClassMappings提供顯式映射
慣例
約定是這樣的,如果你有合同,例如src/test/resources/contract/hello/v1/,并將packageWithBaseClasses屬性的值提供給hello,那么我們將假設(shè)在hello下有一個HelloV1Base類包。換句話說,如果它們存在并且形成具有Base后綴的類,那么我們將使用最后兩個包的部分。優(yōu)先于baseClassForTests。使用示例:
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<configuration>
<packageWithBaseClasses>hello</packageWithBaseClasses>
</configuration>
</plugin>
制圖
您可以手動將合同包的正則表達(dá)式映射為匹配合同的基類的完全限定名稱。您必須提供baseClassMappings baseClassMapping的contractPackageRegex列表contractPackageRegex到baseClassFQN映射。我們來看看下面的例子:
<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<configuration>
<baseClassForTests>com.example.FooBase</baseClassForTests>
<baseClassMappings>
<baseClassMapping>
<contractPackageRegex>.*com.*</contractPackageRegex>
<baseClassFQN>com.example.TestBase</baseClassFQN>
</baseClassMapping>
</baseClassMappings>
</configuration>
</plugin>
我們假設(shè)你有合同 - src/test/resources/contract/com/ - src/test/resources/contract/foo/
通過提供baseClassForTests,我們有一個后備程序,如果映射沒有成功(你也可以提供packageWithBaseClasses作為備用)。這樣,從src/test/resources/contract/com/合同生成的測試將擴展com.example.ComBase,而其余的測試將擴展com.example.FooBase。
調(diào)用生成的測試
Spring Cloud Contract Maven插件將驗證碼生成到目錄/generated-test-sources/contractVerifier中,并將此目錄附加到testCompile目標(biāo)。
對于Groovy Spock代碼使用:
<plugin>
<groupId>org.codehaus.gmavenplus</groupId>
<artifactId>gmavenplus-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
<configuration>
<testSources>
<testSource>
<directory>${project.basedir}/src/test/groovy</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</testSource>
<testSource>
<directory>${project.build.directory}/generated-test-sources/contractVerifier</directory>
<includes>
<include>**/*.groovy</include>
</includes>
</testSource>
</testSources>
</configuration>
</plugin>
為了確保提供方對定義的合同進(jìn)行投訴,您需要調(diào)用mvn generateTest test
Maven插件常見問題
Maven插件和STS
如果在使用STS時看到以下異常
STS異常
當(dāng)您點擊標(biāo)記時,您應(yīng)該看到這樣的sth
plugin:1.1.0.M1:convert:default-convert:process-test-resources) org.apache.maven.plugin.PluginExecutionException: Execution default-convert of goal org.springframework.cloud:spring-
cloud-contract-maven-plugin:1.1.0.M1:convert failed. at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:145) at
org.eclipse.m2e.core.internal.embedder.MavenImpl.execute(MavenImpl.java:331) at org.eclipse.m2e.core.internal.embedder.MavenImpl$11.call(MavenImpl.java:1362) at
...
org.eclipse.core.internal.jobs.Worker.run(Worker.java:55) Caused by: java.lang.NullPointerException at
org.eclipse.m2e.core.internal.builder.plexusbuildapi.EclipseIncrementalBuildContext.hasDelta(EclipseIncrementalBuildContext.java:53) at
org.sonatype.plexus.build.incremental.ThreadBuildContext.hasDelta(ThreadBuildContext.java:59) at
為了解決這個問題,請在pom.xml中提供以下部分
<build>
? ? <pluginManagement>
? ? ? ? <plugins>
? ? ? ? ? ? <!--This plugin's configuration is used to store Eclipse m2e settings
? ? ? ? ? ? ? ? only. It has no influence on the Maven build itself. -->
? ? ? ? ? ? <plugin>
? ? ? ? ? ? ? ? <groupId>org.eclipse.m2e</groupId>
? ? ? ? ? ? ? ? <artifactId>lifecycle-mapping</artifactId>
? ? ? ? ? ? ? ? <version>1.0.0</version>
? ? ? ? ? ? ? ? <configuration>
? ? ? ? ? ? ? ? ? ? <lifecycleMappingMetadata>
? ? ? ? ? ? ? ? ? ? ? ? <pluginExecutions>
? ? ? ? ? ? ? ? ? ? ? ? ? ? <pluginExecution>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <pluginExecutionFilter>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <groupId>org.springframework.cloud</groupId>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <artifactId>spring-cloud-contract-maven-plugin</artifactId>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <versionRange>[1.0,)</versionRange>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <goals>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <goal>convert</goal>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </goals>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </pluginExecutionFilter>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <action>
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? <execute />
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? </action>
? ? ? ? ? ? ? ? ? ? ? ? ? ? </pluginExecution>
? ? ? ? ? ? ? ? ? ? ? ? </pluginExecutions>
? ? ? ? ? ? ? ? ? ? </lifecycleMappingMetadata>
? ? ? ? ? ? ? ? </configuration>
? ? ? ? ? ? </plugin>
? ? ? ? </plugins>
? ? </pluginManagement>
</build>
Spring Cloud Contract消費者驗證者
您實際上也可以為消費者使用Spring Cloud Contract驗證器!您可以使用插件,以便只轉(zhuǎn)換合同并生成存根。要實現(xiàn)這一點,您需要以與提供程序相同的方式配置Spring Cloud Contract驗證程序插件。您需要復(fù)制存儲在src/test/resources/contracts中的合同,并使用以下命令生成WireMock json存根:mvn generateStubs命令。默認(rèn)生成的WireMock映射存儲在目錄target/mappings中。您的項目應(yīng)該從此生成的映射創(chuàng)建附加工件與分類器stubs,以便輕松部署到maven存儲庫。
樣品配置:
<plugin>
? ? <groupId>org.springframework.cloud</groupId>
? ? <artifactId>spring-cloud-contract-maven-plugin</artifactId>
? ? <version>${verifier-plugin.version}</version>
? ? <executions>
? ? ? ? <execution>
? ? ? ? ? ? <goals>
? ? ? ? ? ? ? ? <goal>convert</goal>
? ? ? ? ? ? ? ? <goal>generateStubs</goal>
? ? ? ? ? ? </goals>
? ? ? ? </execution>
? ? </executions>
</plugin>
當(dāng)存在時,json存根可用于消費者自動測試。
@RunWith(SpringTestRunner.class)
@SpringBootTest
@AutoConfigureStubRunner
public class LoanApplicationServiceTests {
? @Autowired
? LoanApplicationService service;
? @Test
? public void shouldSuccessfullyApplyForLoan() {
? ? //given:
LoanApplication application =
new LoanApplication(new Client("12345678901"), 123.123);
? ? //when:
LoanApplicationResult loanApplication = service.loanApplication(application);
? ? // then:
assertThat(loanApplication.loanApplicationStatus).isEqualTo(LoanApplicationStatus.LOAN_APPLIED);
assertThat(loanApplication.rejectionReason).isNull();
? }
}
LoanApplication下方致電FraudDetection服務(wù)。此請求由使用Spring Cloud Contract驗證器生成的存根配置的WireMock服務(wù)器進(jìn)行處理。
方案
可以使用Spring Cloud Contract驗證程序處理場景。所有您需要做的是在創(chuàng)建合同時堅持正確的命名約定。公約要求包括后面是下劃線的訂單號。
my_contracts_dir\
? scenario1\
? ? 1_login.groovy
? ? 2_showCart.groovy
? ? 3_logout.groovy
這樣的樹將導(dǎo)致Spring Cloud Contract驗證器生成名為scenario1的WireMock場景和三個步驟:
? ? 登錄標(biāo)記為Started,指向:
? ? showCart標(biāo)記為Step1指向:
? ? 注銷標(biāo)記為Step2,這將關(guān)閉場景。
有關(guān)WireMock場景的更多詳細(xì)信息,請參見http://wiremock.org/stateful-behaviour.html
Spring Cloud Contract驗證者還將生成具有保證執(zhí)行順序的測試。
存根和傳遞依賴
我們創(chuàng)建的Maven和Gradle插件是為您添加創(chuàng)建存根jar的任務(wù)??赡苡袉栴}的是,當(dāng)重用存根時,您可以錯誤地導(dǎo)入所有這些存根依賴關(guān)系!即使你有幾個不同的罐子,建造一個Maven的工件,他們都有一個pom:
├── github-webhook-0.0.1.BUILD-20160903.075506-1-stubs.jar
├── github-webhook-0.0.1.BUILD-20160903.075506-1-stubs.jar.sha1
├── github-webhook-0.0.1.BUILD-20160903.075655-2-stubs.jar
├── github-webhook-0.0.1.BUILD-20160903.075655-2-stubs.jar.sha1
├── github-webhook-0.0.1.BUILD-SNAPSHOT.jar
├── github-webhook-0.0.1.BUILD-SNAPSHOT.pom
├── github-webhook-0.0.1.BUILD-SNAPSHOT-stubs.jar
├── ...
└── ...
使用這些依賴關(guān)系有三種可能性,以便不會對傳遞依賴性產(chǎn)生任何問題。
將所有應(yīng)用程序依賴項標(biāo)記為可選
如果在github-webhook應(yīng)用程序中,我們將所有的依賴項標(biāo)記為可選的,當(dāng)您將github-webhook存根包含在另一個應(yīng)用程序中(或者當(dāng)依賴關(guān)系由Stub Runner下載)時,因為所有的依賴關(guān)系是可選的,它們不會被下載。
為存根創(chuàng)建一個單獨的artifactid
如果你創(chuàng)建一個單獨的artifactid,那么你可以設(shè)置任何你想要的方式。例如通過沒有依賴關(guān)系。
排除消費者方面的依賴關(guān)系
作為消費者,如果將stub依賴關(guān)系添加到類路徑中,則可以顯式排除不需要的依賴關(guān)系。