跳到主要内容

在 Git 中使用 Stub 进行 Provider 契约测试

DeepSeek V3 中英对照 Provider Contract Testing with Stubs in Git

在此流程中,我们执行提供者契约测试(生产者不了解消费者如何使用其API)。存根被上传到一个独立的仓库(它们不会被上传到 Artifactory 或 Nexus)。

先决条件​

在使用 git 中的存根测试提供者合约之前,您必须提供一个包含每个生产者所有存根的 git 仓库。有关此类项目的示例,请参阅 此示例 或 此示例。推送存根后,仓库将具有以下结构:

$ tree .
└── META-INF
   └── folder.with.group.id.as.its.name
   └── folder-with-artifact-id
   └── folder-with-version
   ├── contractA.groovy
   ├── contractB.yml
   └── contractC.groovy

您还必须提供已设置 Spring Cloud Contract Stub Runner 的消费者代码。有关此类项目的示例,请参阅此示例并搜索 BeerControllerGitTest 测试。您还必须提供已设置 Spring Cloud Contract 的生产者代码以及相应的插件。有关此类项目的示例,请参阅此示例。

流程​

该流程与开发首个基于Spring Cloud Contract的应用程序中展示的完全一致,但Stub Storage的实现是一个git仓库。

你可以在文档的操作指南页面中阅读更多关于设置 git 仓库以及配置消费者端和生产者端的信息。

消费者设置​

为了从 Git 仓库而非 Nexus 或 Artifactory 获取存根,你需要在 Stub Runner 的 repositoryRoot 属性 URL 中使用 git 协议。以下示例展示了如何设置:

注解

@AutoConfigureStubRunner(
stubsMode = StubRunnerProperties.StubsMode.REMOTE,
repositoryRoot = "git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git",
ids = "com.example:artifact-id:0.0.1")

JUnit 4 规则

@Rule
public StubRunnerRule rule = new StubRunnerRule()
.downloadStub("com.example","artifact-id", "0.0.1")
.repoRoot("git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git")
.stubsMode(StubRunnerProperties.StubsMode.REMOTE);

JUnit 5 扩展

@RegisterExtension
public StubRunnerExtension stubRunnerExtension = new StubRunnerExtension()
.downloadStub("com.example","artifact-id", "0.0.1")
.repoRoot("git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git")
.stubsMode(StubRunnerProperties.StubsMode.REMOTE);

设置生产者​

若要将存根推送至 Git 仓库而非 Nexus 或 Artifactory,您需要在插件配置的 URL 中使用 git 协议。同时,您需要明确告知插件在构建过程结束时推送存根。以下示例展示了如何在 Maven 和 Gradle 中实现此操作:

Maven

<plugin>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-contract-maven-plugin</artifactId>
<version>${spring-cloud-contract.version}</version>
<extensions>true</extensions>
<configuration>
<!-- Base class mappings etc. -->

<!-- We want to pick contracts from a Git repository -->
<contractsRepositoryUrl>git://git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git</contractsRepositoryUrl>

<!-- We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts -->
<contractDependency>
<groupId>${project.groupId}</groupId>
<artifactId>${project.artifactId}</artifactId>
<version>${project.version}</version>
</contractDependency>

<!-- The contracts mode can't be classpath -->
<contractsMode>REMOTE</contractsMode>
</configuration>
<executions>
<execution>
<phase>package</phase>
<goals>
<!-- By default we will not push the stubs back to SCM,
you have to explicitly add it as a goal -->
<goal>pushStubsToScm</goal>
</goals>
</execution>
</executions>
</plugin>

Gradle

contracts {
// We want to pick contracts from a Git repository
contractDependency {
stringNotation = "${project.group}:${project.name}:${project.version}"
}
/*
We reuse the contract dependency section to set up the path
to the folder that contains the contract definitions. In our case the
path will be /groupId/artifactId/version/contracts
*/
contractRepository {
repositoryUrl = "git://git://git@github.com:spring-cloud-samples/spring-cloud-contract-nodejs-contracts-git.git"
}
// The mode can't be classpath
contractsMode = "REMOTE"
// Base class mappings etc.
}

/*
In this scenario we want to publish stubs to SCM whenever
the `publish` task is run
*/
publish.dependsOn("publishStubsToScm")

你可以在文档的操作指南部分了解更多关于设置 git 仓库的信息。