Stub Runner Core

Stub runner core 執行服務協作者的 Stub。將 Stub 視為服務的契約,讓您可以使用 stub-runner 作為 消費者驅動契約 的實作。

Stub Runner 可讓您自動下載所提供依賴項的 Stub (或從類別路徑中選取),為它們啟動 WireMock 伺服器,並以適當的 Stub 定義饋送它們。對於訊息傳遞,定義了特殊的 Stub 路徑。

擷取 Stub

您可以從以下選項中選擇取得 Stub

  • 基於 Aether 的解決方案,可從 Artifactory 或 Nexus 下載包含 Stub 的 JAR

  • 類別路徑掃描解決方案,使用模式搜尋類別路徑以擷取 Stub

  • 編寫您自己的 org.springframework.cloud.contract.stubrunner.StubDownloaderBuilder 實作以進行完全客製化

後者範例在 自訂 Stub Runner 章節中描述。

下載 Stub

您可以使用 stubsMode 開關控制 Stub 的下載。它從 StubRunnerProperties.StubsMode 列舉中選取值。您可以使用以下選項

  • StubRunnerProperties.StubsMode.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)

類別路徑掃描

如果您將 stubsMode 屬性設定為 StubRunnerProperties.StubsMode.CLASSPATH (或不設定任何內容,因為 CLASSPATH 是預設值),則會掃描類別路徑。請考慮以下範例

@AutoConfigureStubRunner(ids = {
    "com.example:beer-api-producer:+:stubs:8095",
    "com.example.foo:bar:1.0.0:superstubs:8096"
})

您可以將依賴項新增至您的類別路徑,如下所示

Maven
<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>
Gradle
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,將掃描以下位置

  • /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 時,您必須明確提供群組和 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

透過維護此結構,將掃描類別路徑,您可以在不需要下載 Artifact 的情況下從訊息傳遞或 HTTP Stub 中獲益。

設定 HTTP 伺服器 Stub

Stub Runner 具有 HttpServerStub 的概念,它抽象化了 HTTP 伺服器的底層具體實作 (例如,WireMock 是其中一種實作)。有時,您需要對 Stub 伺服器執行一些額外的調整 (對於給定的實作而言是具體的)。為了做到這一點,Stub Runner 為您提供了 httpServerStubConfigurer 屬性,該屬性在註解和 JUnit 規則中可用,並且可以透過系統屬性存取,您可以在其中提供 org.springframework.cloud.contract.stubrunner.HttpServerStubConfigurer 介面的實作。這些實作可以更改給定 HTTP 伺服器 Stub 的組態檔案。

Spring Cloud Contract Stub Runner 隨附一個您可以為 WireMock 擴充的實作:org.springframework.cloud.contract.stubrunner.provider.wiremock.WireMockHttpServerStubConfigurer。在 configure 方法中,您可以為給定的 Stub 提供您自己的自訂組態。用例可能是在 HTTPS 連接埠上為給定的 Artifact ID 啟動 WireMock。以下範例示範如何執行此操作

範例 1. WireMockHttpServerStubConfigurer 實作
@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"
},
...
]

訊息傳遞 Stub

根據提供的 Stub Runner 依賴項和 DSL,訊息傳遞路徑會自動設定。