SpringCloud 三分鐘游

2023-12-06 17:04 更新

此簡短的導(dǎo)覽使用Spring Cloud Contract來完成:

  • 名為“在生產(chǎn)者端”的部分
  • “消費者方面”一節(jié)

您可以在這里找到更簡短的導(dǎo)覽 。

在生產(chǎn)者方面

要開始使用Spring Cloud Contract,請將具有REST/消息傳遞合同(以Groovy DSL或YAML表示)的文件添加到由contractsDslDir屬性設(shè)置的合同目錄中。默認情況下,它是$rootDir/src/test/resources/contracts

對于HTTP存根,合同定義了應(yīng)針對給定請求返回的響應(yīng)類型(考慮到HTTP方法,URL,標頭,狀態(tài)碼等)。以下示例顯示了Groovy DSL中的HTTP存根如何收縮:

package contracts

org.springframework.cloud.contract.spec.Contract.make {
	request {
		method 'PUT'
		url '/fraudcheck'
		body([
			   "client.id": $(regex('[0-9]{10}')),
			   loanAmount: 99999
		])
		headers {
			contentType('application/json')
		}
	}
	response {
		status OK()
		body([
			   fraudCheckStatus: "FRAUD",
			   "rejection.reason": "Amount too high"
		])
		headers {
			contentType('application/json')
		}
	}
}

YAML中表示的同一合同應(yīng)類似于以下示例:

request:
  method: PUT
  url: /fraudcheck
  body:
    "client.id": 1234567890
    loanAmount: 99999
  headers:
    Content-Type: application/json
  matchers:
    body:
      - path: $.['client.id']
        type: by_regex
        value: "[0-9]{10}"
response:
  status: 200
  body:
    fraudCheckStatus: "FRAUD"
    "rejection.reason": "Amount too high"
  headers:
    Content-Type: application/json;charset=UTF-8

對于消息傳遞,可以定義:

  • 可以定義輸入和輸出消息(考慮發(fā)送消息的位置和位置,消息正文和標頭)。
  • 收到消息后應(yīng)調(diào)用的方法。
  • 調(diào)用時應(yīng)觸發(fā)消息的方法。

以下示例顯示了以Groovy DSL表示的駱駝消息傳遞協(xié)定:

			def contractDsl = Contract.make {
				label 'some_label'
				input {
					messageFrom('jms:delete')
					messageBody([
							bookName: 'foo'
					])
					messageHeaders {
						header('sample', 'header')
					}
					assertThat('bookWasDeleted()')
				}
			}

以下示例顯示了用YAML表示的同一合同:

label: some_label
input:
  messageFrom: jms:delete
  messageBody:
    bookName: 'foo'
  messageHeaders:
    sample: header
  assertThat: bookWasDeleted()

然后,您可以將Spring Cloud Contract Verifier依賴項和插件添加到您的構(gòu)建文件中,如以下示例所示:

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-contract-verifier</artifactId>
	<scope>test</scope>
</dependency>

以下清單顯示了如何添加插件,該插件應(yīng)放在文件的build / plugins部分中:

<plugin>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-contract-maven-plugin</artifactId>
	<version>${spring-cloud-contract.version}</version>
	<extensions>true</extensions>
</plugin>

運行./mvnw clean install會自動生成測試,以驗證應(yīng)用程序是否符合添加的合同。默認情況下,生成的測試在org.springframework.cloud.contract.verifier.tests.下。

以下示例顯示了自動生成的HTTP合同測試示例:

@Test
public void validate_shouldMarkClientAsFraud() throws Exception {
    // given:
        MockMvcRequestSpecification request = given()
                .header("Content-Type", "application/vnd.fraud.v1+json")
                .body("{\"client.id\":\"1234567890\",\"loanAmount\":99999}");

    // when:
        ResponseOptions response = given().spec(request)
                .put("/fraudcheck");

    // then:
        assertThat(response.statusCode()).isEqualTo(200);
        assertThat(response.header("Content-Type")).matches("application/vnd.fraud.v1.json.*");
    // and:
        DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
        assertThatJson(parsedJson).field("['fraudCheckStatus']").matches("[A-Z]{5}");
        assertThatJson(parsedJson).field("['rejection.reason']").isEqualTo("Amount too high");
}

前面的示例使用Spring的MockMvc運行測試。這是HTTP合同的默認測試模式。但是,也可以使用JAX-RS客戶端和顯式HTTP調(diào)用。(為此,請將插件的testMode屬性分別更改為JAX-RSEXPLICIT。)

從2.1.0版開始,也可以使用RestAssuredWebTestClient`with Spring’s reactive `WebTestClient在后臺運行。在使用基于Web-Flux的響應(yīng)式應(yīng)用程序時,特別推薦使用此方法。為了使用WebTestClient,請將testMode設(shè)置為WEBTESTCLIENT。

這是在WEBTESTCLIENT測試模式下生成的測試的示例:

[source,java,indent=0]
@Test
	public void validate_shouldRejectABeerIfTooYoung() throws Exception {
		// given:
			WebTestClientRequestSpecification request = given()
					.header("Content-Type", "application/json")
					.body("{\"age\":10}");

		// when:
			WebTestClientResponse response = given().spec(request)
					.post("/check");

		// then:
			assertThat(response.statusCode()).isEqualTo(200);
			assertThat(response.header("Content-Type")).matches("application/json.*");
		// and:
			DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
			assertThatJson(parsedJson).field("['status']").isEqualTo("NOT_OK");
	}

除了默認的JUnit 4,您可以通過將插件的testFramework屬性設(shè)置為JUNIT5Spock來使用JUnit 5或Spock測試。

 現(xiàn)在,您還可以基于合同生成WireMock方案,方法是在合同文件名的開頭添加訂單號,后跟下劃線。

以下示例顯示了在Spock中為消息存根合約自動生成的測試:

[source,groovy,indent=0]
given:
	 ContractVerifierMessage inputMessage = contractVerifierMessaging.create(
		\'\'\'{"bookName":"foo"}\'\'\',
		['sample': 'header']
	)

when:
	 contractVerifierMessaging.send(inputMessage, 'jms:delete')

then:
	 noExceptionThrown()
	 bookWasDeleted()

由于尚不存在合同描述的功能的實現(xiàn),因此測試失敗。

要使它們通過,您必須添加處理HTTP請求或消息的正確實現(xiàn)。另外,您必須為自動生成的測試添加正確的基礎(chǔ)測試類。該類由所有自動生成的測試擴展,并且應(yīng)包含運行它們所需的所有設(shè)置(例如,RestAssuredMockMvc控制器設(shè)置或消息傳遞測試設(shè)置)。

一旦實現(xiàn)和測試基類就位,測試就會通過,并且將應(yīng)用程序和存根構(gòu)件都構(gòu)建并安裝在本地Maven存儲庫中。有關(guān)將存根jar安裝到本地存儲庫的信息顯示在日志中,如以下示例所示:

[INFO] --- spring-cloud-contract-maven-plugin:1.0.0.BUILD-SNAPSHOT:generateStubs (default-generateStubs) @ http-server ---
[INFO] Building jar: /some/path/http-server/target/http-server-0.0.1-SNAPSHOT-stubs.jar
[INFO]
[INFO] --- maven-jar-plugin:2.6:jar (default-jar) @ http-server ---
[INFO] Building jar: /some/path/http-server/target/http-server-0.0.1-SNAPSHOT.jar
[INFO]
[INFO] --- spring-boot-maven-plugin:1.5.5.BUILD-SNAPSHOT:repackage (default) @ http-server ---
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ http-server ---
[INFO] Installing /some/path/http-server/target/http-server-0.0.1-SNAPSHOT.jar to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT.jar
[INFO] Installing /some/path/http-server/pom.xml to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT.pom
[INFO] Installing /some/path/http-server/target/http-server-0.0.1-SNAPSHOT-stubs.jar to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT-stubs.jar

現(xiàn)在,您可以合并更改,并在在線存儲庫中發(fā)布應(yīng)用程序和存根工件。

Docker項目

為了在使用非JVM技術(shù)創(chuàng)建應(yīng)用程序時啟用合同,已經(jīng)創(chuàng)建了springcloud/spring-cloud-contract Docker映像。它包含一個項目,該項目會自動為HTTP合同生成測試并以EXPLICIT測試模式執(zhí)行它們。然后,如果測試通過,它將生成Wiremock存根并將其發(fā)布到工件管理器(可選)。 為了使用該映像,您可以將合同掛載到/contracts目錄中并設(shè)置一些環(huán)境變量。

在消費者方面

Spring Cloud Contract Stub Runner可用于集成測試中,以獲取模擬實際服務(wù)的正在運行的WireMock實例或消息傳遞路由。

首先,將依賴項添加到Spring Cloud Contract Stub Runner

<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-contract-stub-runner</artifactId>
	<scope>test</scope>
</dependency>

您可以通過以下兩種方式之一在Maven存儲庫中安裝生產(chǎn)者端存根:

  • 通過檢出生產(chǎn)者端存儲庫并添加合同并通過運行以下命令來生成存根:

    $ cd local-http-server-repo
    $ ./mvnw clean install -DskipTests

    由于生產(chǎn)者方合同實施尚未到位,因此跳過了測試,因此自動生成的合同測試失敗。

  • 從遠程存儲庫獲取已經(jīng)存在的生產(chǎn)者服務(wù)存根。為此,請將存根工件標識和工件存儲庫UR1作為Spring Cloud Contract Stub Runner屬性傳遞,如以下示例所示:

    stubrunner:
      ids: 'com.example:http-server-dsl:+:stubs:8080'
      repositoryRoot: https://repo.spring.io/libs-snapshot

現(xiàn)在,您可以使用@AutoConfigureStubRunner注釋測試類。在注釋中,為Spring Cloud Contract Stub Runner提供group-idartifact-id以便為您運行協(xié)作者的存根,如以下示例所示:

@RunWith(SpringRunner.class)
@SpringBootTest(webEnvironment=WebEnvironment.NONE)
@AutoConfigureStubRunner(ids = {"com.example:http-server-dsl:+:stubs:6565"},
		stubsMode = StubRunnerProperties.StubsMode.LOCAL)
public class LoanApplicationServiceTests {

 從在線存儲庫下載存根時,請使用REMOTE stubsMode,而對于脫機工作,請使用 LOCAL

在集成測試中,您可以接收HTTP響應(yīng)的殘存版本或預(yù)期由協(xié)作服務(wù)發(fā)出的消息。您可以在構(gòu)建日志中看到類似于以下內(nèi)容的條目:

2016-07-19 14:22:25.403  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Desired version is + - will try to resolve the latest version
2016-07-19 14:22:25.438  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved version is 0.0.1-SNAPSHOT
2016-07-19 14:22:25.439  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolving artifact com.example:http-server:jar:stubs:0.0.1-SNAPSHOT using remote repositories []
2016-07-19 14:22:25.451  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Resolved artifact com.example:http-server:jar:stubs:0.0.1-SNAPSHOT to /path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT-stubs.jar
2016-07-19 14:22:25.465  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacking stub from JAR [URI: file:/path/to/your/.m2/repository/com/example/http-server/0.0.1-SNAPSHOT/http-server-0.0.1-SNAPSHOT-stubs.jar]
2016-07-19 14:22:25.475  INFO 41050 --- [           main] o.s.c.c.stubrunner.AetherStubDownloader  : Unpacked file to [/var/folders/0p/xwq47sq106x1_g3dtv6qfm940000gq/T/contracts100276532569594265]
2016-07-19 14:22:27.737  INFO 41050 --- [           main] o.s.c.c.stubrunner.StubRunnerExecutor    : All stubs are now running RunningStubs [namesAndPorts={com.example:http-server:0.0.1-SNAPSHOT:stubs=8080}]


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號