Stub Runner 核心
Stub Runner 核心為服務協作方執行 Stub。將 Stub 視為服務契約,使你可以將 Stub Runner 用作消費者驅動契約的實現。
Stub Runner 允許你自動下載所提供依賴項的 Stub(或從 classpath 中選取),為它們啟動 WireMock 伺服器,並提供適當的 Stub 定義。對於訊息傳遞,定義了特殊的 Stub 路由。
檢索 Stub
你可以從以下選項中選擇獲取 Stub 的方式
-
基於 Aether 的解決方案,從 Artifactory 或 Nexus 下載包含 Stub 的 JAR
-
Classpath 掃描解決方案,使用模式搜尋 classpath 以檢索 Stub
-
編寫你自己的
org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder
實現以進行完全自定義
後一個示例在自定義 Stub Runner 部分有所描述。
下載 Stub
你可以使用 stubsMode
開關控制 Stub 的下載。它從 StubRunnerProperties.StubsMode
列舉中選取值。你可以使用以下選項
-
StubRunnerProperties.StubsMode.CLASSPATH
(預設值):從 classpath 中選取 Stub -
StubRunnerProperties.StubsMode.LOCAL
:從本地儲存(例如,.m2
)中選取 Stub -
StubRunnerProperties.StubsMode.REMOTE
:從遠端位置選取 Stub
以下示例從本地位置選取 Stub
@AutoConfigureStubRunner(repositoryRoot="https://foo.bar", ids = "com.example:beer-api-producer:+:stubs:8095", stubsMode = StubRunnerProperties.StubsMode.LOCAL)
Classpath 掃描
如果你將 stubsMode
屬性設定為 StubRunnerProperties.StubsMode.CLASSPATH
(或者不設定,因為 CLASSPATH
是預設值),則會掃描 classpath。考慮以下示例
@AutoConfigureStubRunner(ids = {
"com.example:beer-api-producer:+:stubs:8095",
"com.example.foo:bar:1.0.0:superstubs:8096"
})
你可以將依賴項新增到 classpath,如下所示
<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
}
然後掃描 classpath 上指定的位置。對於 com.example:beer-api-producer-restdocs
,會掃描以下位置
-
/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
,會掃描以下位置
-
/META-INF/com.example.thing1/thing2/*/.*
-
/contracts/com.example.thing1/thing2/*/.*
-
/mappings/com.example.thing1/thing2/*/.*
打包生產者 Stub 時,必須明確提供 group 和 artifact ID。 |
為實現正確的 Stub 打包,生產者需要按如下方式設定契約
└── src
└── test
└── resources
└── contracts
└── com.example
└── beer-api-producer-restdocs
└── nested
└── contract3.groovy
透過使用Maven assembly
外掛或Gradle Jar 任務,你必須在 Stub JAR 中建立以下結構
└── META-INF
└── com.example
└── beer-api-producer-restdocs
└── 2.0.0
├── contracts
│ └── nested
│ └── contract2.groovy
└── mappings
└── mapping.json
透過維護此結構,classpath 會被掃描,你可以直接使用訊息傳遞或 HTTP Stub,無需下載 artifact。
配置 HTTP 伺服器 Stub
Stub Runner 有一個 HttpServerStub
的概念,它抽象了底層具體的 HTTP 伺服器實現(例如,WireMock 是其中一種實現)。有時,你需要對 Stub 伺服器進行一些額外的調整(這取決於具體的實現)。為此,Stub Runner 提供了 httpServerStubConfigurer
屬性,該屬性在註解和 JUnit Rule 中可用,並且可以透過系統屬性訪問,你可以在其中提供 org.springframework.cloud.contract.stubrunner.HttpServerStubConfigurer
介面的實現。這些實現可以修改給定 HTTP 伺服器 Stub 的配置檔案。
Spring Cloud Contract Stub Runner 提供了一個你可以為 WireMock 擴充套件的實現:org.springframework.cloud.contract.stubrunner.provider.wiremock.WireMockHttpServerStubConfigurer
。在 configure
方法中,你可以為給定 Stub 提供自己的自定義配置。用例可能是為給定 artifact ID 在 HTTPS 埠上啟動 WireMock。以下示例展示瞭如何實現
@CompileStatic
static class HttpsForFraudDetection extends WireMockHttpServerStubConfigurer {
private static final Log log = LogFactory.getLog(HttpsForFraudDetection)
@Override
WireMockConfiguration configure(WireMockConfiguration httpStubConfiguration, HttpServerStubConfiguration httpServerStubConfiguration) {
if (httpServerStubConfiguration.stubConfiguration.artifactId == "fraudDetectionServer") {
int httpsPort = TestSocketUtils.findAvailableTcpPort()
log.info("Will set HTTPs port [" + httpsPort + "] for fraud detection server")
return httpStubConfiguration
.httpsPort(httpsPort)
}
return httpStubConfiguration
}
}
然後你可以使用 @AutoConfigureStubRunner
註解重用它,如下所示
@AutoConfigureStubRunner(mappingsOutputFolder = "target/outputmappings/",
httpServerStubConfigurer = HttpsForFraudDetection)
無論何時發現 HTTPS 埠,它都優先於 HTTP 埠。
執行 Stub
本節描述如何執行 Stub。它包含以下主題
HTTP Stub
Stub 定義在 JSON 文件中,其語法在WireMock 文件中定義。
以下示例在 JSON 中定義了一個 Stub
{
"request": {
"method": "GET",
"url": "/ping"
},
"response": {
"status": 200,
"body": "pong",
"headers": {
"Content-Type": "text/plain"
}
}
}
檢視已註冊的對映
每個 Stub 協作方都在 __/admin/
端點下暴露已定義的對映列表。
你還可以使用 mappingsOutputFolder
屬性將對映匯出到檔案。對於基於註解的方法,類似於以下示例
@AutoConfigureStubRunner(ids="a.b.c:loanIssuance,a.b.c:fraudDetectionServer",
mappingsOutputFolder = "target/outputmappings/")
對於 JUnit 方法,類似於以下示例
@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
資料夾,會看到以下結構;
.
├── fraudDetectionServer_13705
└── loanIssuance_12255
這意味著註冊了兩個 Stub。fraudDetectionServer
註冊在埠 13705
,loanIssuance
註冊在埠 12255
。如果我們檢視其中一個檔案,會看到(對於 WireMock)給定伺服器可用的對映
[{
"id" : "f9152eb9-bf77-4c38-8289-90be7d10d0d7",
"request" : {
"url" : "/name",
"method" : "GET"
},
"response" : {
"status" : 200,
"body" : "fraudDetectionServer"
},
"uuid" : "f9152eb9-bf77-4c38-8289-90be7d10d0d7"
},
...
]