java -jar wiremock-standalone-2.11.0.jar
{
"request" : {
"urlPath" : "/api/order/find",
"method" : "GET",
"queryParameters" : {
"orderId" : {
"matches" : "^[0-9]{16}$"
}
}
},
"response" : {
"status" : 200,
"bodyFileName" : "body-order-find-1.json",
"essay-headers" : {
"Content-Type" : "application/json;charset=UTF-8"
}
}
}
{
"success": true,
"data": {
"id": 781202,
"buyerId": -2,
"status": 0,
// 略...
}
}
$ curl http://localhost:8080/api/order/find?orderId=abcdefghijklmnop
Request was not matched
=======================
----------------------------------------------
| Closest stub | Request
----------------------------------------------
GET | GET
/api/order/find | /api/order/find
----------------------------------------------
$ curl http://localhost:8080/api/order/find?orderId=9999999999999999
{
"success": true,
"data": {
"id": 781202,
"buyerId": -2,
"status": 0
}
}
-
透過 RESTFul 的介面提交和管理請求對映和相應。
-
支援響應模板,傳回內容時會將變數填充到響應模板中。當然,這裡的模板功能是比較簡單的,但對於大部分 Stub 的場景應該是足夠了。
-
支援模擬異常傳回,例如設定有一定比例的超時傳回等等,這個功能用於測試非常方便。
public class OrderTest {
@Rule
public WireMockRule wireMockRule = new WireMockRule(9090);
/**
* 統一下單 Stub
* 參考 https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=9_1
*
* @param tradeType 交易型別,可以是JSAPI、NATIVE或APP
*/
public void stubForUnifiedOrderSuccess(String tradeType) {
String unifiedOrderResp = "<xml>\n" +
" <return_code>return_code>
\n” +
” <return_msg>return_msg>\n” +
” <appid>appid>\n” +
” <mch_id>mch_id>\n” +
” …… \n” +
” <trade_type>trade_type>\n” +
“xml>”;
stubFor(post(urlEqualTo(“/pay/unifiedorder”))
.withHeader(“Content-Type”, equalTo(“text/xml;charset=UTF-8”))
.willReturn(aResponse()
.withStatus(200)
.withHeader(“Content-Type”, “text/plain”)
.withBody(unifiedOrderResp)));
}
@Test
public void test001_doPay() {
stubForUnifiedOrderSuccess(“JSAPI”);
payServices.pay();
// 測試程式碼…
}
}
verify(postRequestedFor(urlEqualTo("/pay/unifiedorder"))
.withHeader("Content-Type", equalTo("text/xml;charset=UTF-8"))
.withQueryParam("param", equalTo("param1"))
.withRequestBody(containing("success"));
-
作為代理執行,此時可以錄製請求和傳回的指令碼,用於後繼 Stub 和 Mock 使用。
-
獨立執行,作為一個 Stub 服務,根據匹配的請求傳回資料。
-
作為 Stub,透過程式碼嵌入 HTTP 模擬服務,在指定埠監聽,並根據匹配的請求傳回資料。
-
作為 Mock,在單元測試和整合測試中,驗證請求邏輯。例如是否進行了呼叫、引數是否正確等。
-
在外部服務尚未開發完成時,模擬服務,方便開發。
-
在本地開發時,模擬外部服務避免直接依賴。
-
在單元測試中模擬外部服務,同時驗證業務邏輯。
org.springframework.cloud.contract.spec.Contract.make {
// 如果消費方發送了一個請求
request {
// 請求方法是 POST
method 'POST'
// 請求 URL 是 `/sendsms`
url '/sendsms'
// 請求內容是 Json 文字,包括電話號碼和要傳送的文字
body([
// 電話號碼必須是13個數字組成
phone: $(regex('[0-9]{13}')),
// 傳送文字必須為"您好"
content: "您好"
])
}
response {
// 那麼服務方應該傳回狀態碼 200
status 200
// 響應內容是 Json 文字,內容為 { "success": true }
body([
success: true
])
}}
-
業務方和服務方相關人員一起討論。業務方告知服務方介面使用的場景、期望的傳回是什麼,服務方考慮介面方案和實現,雙方一起定下一個或多個契約。
-
確定了契約之後,Spring Cloud Contract 會給服務方自動生成驗收測試,用於驗證介面是否符合契約。服務方要確保開發完成後,這些驗收測試都能夠透過。
-
業務方也可以基於這個契約開始開發功能。Spring Cloud Contract 會基於契約生成 Stub 服務,這樣業務方就不必等介面開發完成,可以透過 Stub 服務進行整合測試。
-
讓服務方和呼叫方有充分的溝通,確保服務方提供介面都是以呼叫方的需求出發,並且服務方的開發者也可以充分理解呼叫方的使用場景。
-
解耦和服務方和呼叫方的開發過程,一旦契約訂立,雙方都可以並行開發,透過 Mock 和自動化整合測試確保雙方都遵守契約,最終整合也會更簡單。
-
透過 Mock 和自動化測試,可以確保雙方在演進過程中,也不會破壞已有的契約。
./gradlew generateContractTests
public class SmsTest extends ContractBase {
@Test
public void validate_sendsms() throws Exception {
// given:
MockMvcRequestSpecification request = given()
.body("{\"phone\":\"2066260255168\",\"content\":\"\u60A8\u597D\"}");
// when:
ResponseOptions response = given().spec(request)
.post("/sendsms");
// then:
assertThat(response.statusCode()).isEqualTo(200);
// and:
DocumentContext parsedJson = JsonPath.parse(response.getBody().asString());
assertThatJson(parsedJson).field("['success']").isEqualTo(true);
}
}
public void setup() {
RestAssuredMockMvc.webAppContextSetup(webApplicationContext);
}
./gradlew verifierStubsJar
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(webEnvironment= SpringBootTest.WebEnvironment.NONE)
@AutoConfigureStubRunner(repositoryRoot="http://" ,
ids = {"com.xingren.service:sms-client-stubs:1.5.0-SNAPSHOT:stubs:6565"})
public class ContractTest {
@Test
public void testSendSms() {
ResponseEntity response =
restTemplate.exchange("http://localhost:6565/sendsms", HttpMethod.POST,
new HttpEntity<>(request), SmsServiceResponse.class);
// do some verification
}
}
$ brew tap pivotal/tap
$ brew install springboot
$ spring install org.springframework.cloud:spring-cloud-cli:1.4.0.RELEASE
stubrunner:
workOffline: false
repositoryRoot: http://
ids:
- com.xingren.service:sms-client-stubs:1.5.0-SNAPSHOT:stubs:6565
org.springframework.cloud.contract.spec.Contract.make {
request {
method('GET')
url $(consumer(~/\/[0-9]{2}/), producer('/12'))
}
response {
status 200
body(
name: $(consumer('Kowalsky'), producer(regex('[a-zA-Z]+')))
)
}
}
本次培訓包含:Kubernetes核心概念;Kubernetes叢集的安裝配置、運維管理、架構規劃;Kubernetes元件、監控、網路;針對於Kubernetes API介面的二次開發;DevOps基本理念;微服務架構;微服務的容器化等,點選識別下方二維碼加微信好友瞭解具體培訓內容。