Stub Runner Core
存根运行器内核会为服务合作者运行存根。将存根视为服务的合约允许您使用存根运行器作为 Consumer-driven Contracts 的实现。
The stub runner core runs stubs for service collaborators. Treating stubs as contracts of services lets you use stub-runner as an implementation of Consumer-driven Contracts.
Stub Runner 允许您自动下载所提供依赖项的 stub(或从类路径中选择那些),为它们启动 WireMock 服务器,并使用适当的 stub 定义为它们提供支持。对于消息传递,将定义特殊的 stub 路由。
Stub Runner lets you automatically download the stubs of the provided dependencies (or pick those from the classpath), start WireMock servers for them, and feed them with proper stub definitions. For messaging, special stub routes are defined.
Retrieving stubs
您可以从以下获取 stub 的选项中进行选择:
You can pick from the following options of acquiring stubs:
-
Aether-based solution that downloads JARs with stubs from Artifactory or Nexus
-
Classpath-scanning solution that searches the classpath with a pattern to retrieve stubs
-
Writing your own implementation of the
org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder
for full customization
后一个示例在 Custom Stub Runner 部分中进行说明了。
The latter example is described in the Custom Stub Runner section.
Downloading Stubs
您可以使用 stubsMode
开关控制 stub 的下载。它从 StubRunnerProperties.StubsMode
枚举中选择值。您可以使用以下选项:
You can control the downloading of stubs with the stubsMode
switch. It picks value from the
StubRunnerProperties.StubsMode
enumeration. You can use the following options:
-
StubRunnerProperties.StubsMode.CLASSPATH
(default value): Picks stubs from the classpath -
StubRunnerProperties.StubsMode.LOCAL
: Picks stubs from a local storage (for example,.m2
) -
StubRunnerProperties.StubsMode.REMOTE
: Picks stubs from a remote location
以下示例从本地位置选择 stub:
The following example picks stubs from a local location:
@AutoConfigureStubRunner(repositoryRoot="https://foo.bar", ids = "com.example:beer-api-producer:+:stubs:8095", stubsMode = StubRunnerProperties.StubsMode.LOCAL)
Classpath scanning
如果您将 stubsMode
属性设置为 StubRunnerProperties.StubsMode.CLASSPATH
(或不设置任何内容,因为 CLASSPATH
是默认值),则扫描类路径。考虑以下示例:
If you set the stubsMode
property to StubRunnerProperties.StubsMode.CLASSPATH
(or set nothing since CLASSPATH
is the default value), the classpath is scanned.
Consider the following example:
@AutoConfigureStubRunner(ids = {
"com.example:beer-api-producer:+:stubs:8095",
"com.example.foo:bar:1.0.0:superstubs:8096"
})
您可以将依赖项添加到类路径,如下所示:
You can add the dependencies to your classpath, as follows:
<dependency>
<groupId>com.example</groupId>
<artifactId>beer-api-producer-restdocs</artifactId>
<classifier>stubs</classifier>
<version>0.0.1-SNAPSHOT</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>com.example.thing1</groupId>
<artifactId>thing2</artifactId>
<classifier>superstubs</classifier>
<version>1.0.0</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>*</groupId>
<artifactId>*</artifactId>
</exclusion>
</exclusions>
</dependency>
testCompile("com.example:beer-api-producer-restdocs:0.0.1-SNAPSHOT:stubs") {
transitive = false
}
testCompile("com.example.thing1:thing2:1.0.0:superstubs") {
transitive = false
}
然后,扫描类路径上的指定位置。对于 com.example:beer-api-producer-restdocs
,扫描以下位置:
Then the specified locations on your classpath get scanned. For com.example:beer-api-producer-restdocs
,
the following locations are scanned:
-
/META-INF/com.example/beer-api-producer-restdocs/*/.*
-
/contracts/com.example/beer-api-producer-restdocs/*/.*
-
/mappings/com.example/beer-api-producer-restdocs/*/.*
对于 com.example.thing1:thing2
,扫描以下位置:
For com.example.thing1:thing2
, the following locations are scanned:
-
/META-INF/com.example.thing1/thing2/*/.*
-
/contracts/com.example.thing1/thing2/*/.*
-
/mappings/com.example.thing1/thing2/*/.*
在你打包producer stub时,必须明确提供组和artifact id。 |
You have to explicitly provide the group and artifact IDs when you package the producer stubs. |
为实现适当的 stub 打包,生产者将按照如下方式设置合同:
To achieve proper stub packaging, the producer would set up the contracts as follows:
└── src
└── test
└── resources
└── contracts
└── com.example
└── beer-api-producer-restdocs
└── nested
└── contract3.groovy
通过使用 Maven assembly
plugin 或 Gradle Jar 任务,您必须在自己的存根 jar 中创建以下结构:
By using the Maven assembly
plugin or the
Gradle Jar task, you have to create the following
structure in your stubs jar:
└── META-INF
└── com.example
└── beer-api-producer-restdocs
└── 2.0.0
├── contracts
│ └── nested
│ └── contract2.groovy
└── mappings
└── mapping.json
通过维护此结构,将扫描类路径并且无需下载工件即可从消息传递或 HTTP 存根中获益。
By maintaining this structure, the classpath gets scanned and you can profit from the messaging or HTTP stubs without the need to download artifacts.
Configuring HTTP Server Stubs
Stub Runner 有一个 HttpServerStub
的概念,它抽象了底层 HTTP 服务器的具体实现(例如,WireMock 是实现之一)。有时,您需要对存根服务器执行一些附加的调整(这对给定的实现是具体的)。要做到这一点,Stub Runner 为您提供了 httpServerStubConfigurer
属性,该属性在注释和 JUnit 规则中可用,并且可以通过系统属性进行访问,您可以在其中提供 org.springframework.cloud.contract.stubrunner.HttpServerStubConfigurer
接口的实现。这些实现可以更改给定 HTTP 服务器存根的配置文件。
Stub Runner has a notion of a HttpServerStub
that abstracts the underlying
concrete implementation of the HTTP server (for example, WireMock is one of the implementations).
Sometimes, you need to perform some additional tuning (which is concrete for the given implementation) of the stub servers.
To do that, Stub Runner gives you
the httpServerStubConfigurer
property that is available in the annotation and the
JUnit rule and is accessible through system properties, where you can provide
your implementation of the org.springframework.cloud.contract.stubrunner.HttpServerStubConfigurer
interface. The implementations can alter
the configuration files for the given HTTP server stub.
Spring Cloud Contract Stub Runner 带有一个可以针对 WireMock 扩展的实现:org.springframework.cloud.contract.stubrunner.provider.wiremock.WireMockHttpServerStubConfigurer
。在 configure
方法中,您可以提供给定存根自己的自定义配置。用例可能是针对给定的工件 ID 在 HTTPS 端口上启动 WireMock。以下示例演示如何执行此操作:
Spring Cloud Contract Stub Runner comes with an implementation that you
can extend for WireMock:
org.springframework.cloud.contract.stubrunner.provider.wiremock.WireMockHttpServerStubConfigurer
.
In the configure
method,
you can provide your own custom configuration for the given stub. The use
case might be starting WireMock for the given artifact ID, on an HTTPS port. The following
example shows how to do so:
Unresolved directive in stub-runner-core.adoc - include::{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfigurationSpec.groovy[]
然后,您可以使用 @AutoConfigureStubRunner
注释对其进行重复使用,如下所示:
You can then reuse it with the @AutoConfigureStubRunner
annotation, as follows:
Unresolved directive in stub-runner-core.adoc - include::{stubrunner_core_path}/src/test/groovy/org/springframework/cloud/contract/stubrunner/spring/StubRunnerConfigurationSpec.groovy[]
每当找到 HTTPS 端口时,它都优先于 HTTP 端口。
Whenever an HTTPS port is found, it takes precedence over the HTTP port.
Running stubs
本节介绍了如何运行存根。它包含以下主题:
This section describes how to run stubs. It contains the following topics:
HTTP Stubs
存根使用 JSON 文档进行定义,其语法由 WireMock documentation 中定义。
Stubs are defined in JSON documents, whose syntax is defined in the WireMock documentation.
以下示例在 JSON 中定义了一个存根:
The following example defines a stub in JSON:
{
"request": {
"method": "GET",
"url": "/ping"
},
"response": {
"status": 200,
"body": "pong",
"headers": {
"Content-Type": "text/plain"
}
}
}
Viewing Registered Mappings
每个存根的合作者都会在 __/admin/
端点下公开一个已定义的映射列表。
Every stubbed collaborator exposes a list of defined mappings under the __/admin/
endpoint.
您还可以使用 mappingsOutputFolder
属性将映射转储到文件中。对于基于注释的方法,它类似于以下示例:
You can also use the mappingsOutputFolder
property to dump the mappings to files.
For the annotation-based approach, it would resembling the following example:
@AutoConfigureStubRunner(ids="a.b.c:loanIssuance,a.b.c:fraudDetectionServer",
mappingsOutputFolder = "target/outputmappings/")
对于 JUnit 方法,它类似于以下示例:
For the JUnit approach, it resembles the following example:
@ClassRule @Shared StubRunnerRule rule = new StubRunnerRule()
.repoRoot("https://some_url")
.downloadStub("a.b.c", "loanIssuance")
.downloadStub("a.b.c:fraudDetectionServer")
.withMappingsOutputFolder("target/outputmappings")
然后,如果您签出 target/outputmappings
文件夹,您将看到以下结构;
Then, if you check out the target/outputmappings
folder, you would see the following structure;
.
├── fraudDetectionServer_13705
└── loanIssuance_12255
这意味着注册了两个存根。fraudDetectionServer
在端口 13705
注册,loanIssuance
在端口 12255
注册。如果我们查看其中一个文件,我们将看到(对于 WireMock)给定服务器可用的映射:
That means that there were two stubs registered. fraudDetectionServer
was registered at port 13705
and loanIssuance
at port 12255
. If we take a look at one of the files, we would see (for WireMock)
the mappings available for the given server:
[{
"id" : "f9152eb9-bf77-4c38-8289-90be7d10d0d7",
"request" : {
"url" : "/name",
"method" : "GET"
},
"response" : {
"status" : 200,
"body" : "fraudDetectionServer"
},
"uuid" : "f9152eb9-bf77-4c38-8289-90be7d10d0d7"
},
...
]