# 第十章 Testing microservices:Part 2 > 微服務架構中的測試策略:Part 2 ## 章節大綱 * 上個章節提到的test pyramid * unit tests * 這節會繼續說明上面的三層 * integration tests * 整合測試驗證服務可以正確與基礎設施服務(像是資料庫)和其他app服務互動 * component tests * 使用stubs代替依賴項,來獨立測試服務 * end-to-end tests * 測試所有的服務或是app ## 10.1 整合測試 * API Gateway 使用 REST API * services 使用 `domain events` * 像是 Order History Service 裡面 Order Service 用好幾個其他的服務 * Orders 儲存在 MySQL * Kitchen Service 對其他服務發送命令還有等待使用他的回覆  * 如果把所有東西一起測試就是最後的 end-to-end tests * 太慢 成本高 又容易出問題 * 用Integration tests  * 以下有兩種方法 * 測試每個服務的配接器(adapters) * 直接測試資料庫 * 使用合約 * 合約是一對服務之間互動的具體範例 * 合約的結構取決於服務之間互動的類型  * consumer-side test - 使用合約來配置可模擬提供程序的stub,來做整合測試 * Provider-side tests - 使用合約對adapters的來測試,adapters的依賴項用mock ### 10.1.1 針對持久化層的整合測試 * unit tests 只有在記憶體裡測試 * persistence integration test的每個階段 * Setup - 創建 database schema 以及初始化 * Execute - 執行動作 * Verify - 驗證從資料庫取回的資料 * Teardown - 讓資料庫變回本狀態 像是回滾之類的操作   * shouldSaveAndLoadOrder() * 執行兩個transaction * 儲存新的訂單 * 載入訂單並驗證 * 資料庫的部分可以用Docker來測試 ### 10.1.2 針對基於REST的 request/response style interactions 的整合測試 * 使用consumer-driven contract tests * API Gateway 跟 GET /orders/{orderId} 的互動可以用 HTTP-based contracts 來表示 * 使用 Spring Cloud Contract 來測試 REST-based interactions * consumer-side API Gateway 整合測試用合約配置的 HTTP stub server 模擬 Order Service 的功能 * Spring Cloud Contract 用合約 **code-generate** provider-side 的 Order Service 整合測試 * 去測試**controllers** * 合約對 controller request 特定的 HTTP request * 合約也對 controller 定好特定的 response  * WireMock * 模擬 HTTP servers — 在這測試裡就是模擬 Order Service * Spring Cloud Contract 會配置好 WireMock * REST API 的合約範例  * 合約指定的 request * the HTTP method * the path * optional headers * 合約指定的 response * the HTTP status code * optional headers * expected body * ORDER SERVICE 的 CDC 整合測試   * HttpBase class * code-generated by Spring Cloud Contract * 設定好模擬的依賴項等等 做到可以產出合約指定的回應 * 當 Order Service 收到 GET/orders/{orderId} 運行OrderRepository’s findById() 後驗證回應是否正確 * CONSUMER-SIDE 整合測試 API GATEWAY’S ORDERSERVICEPROXY   * API Gateway’s OrderServiceProxy 呼叫 GET /orders/{orderId} endpoint * OrderServiceProxyIntegrationTest test class * 驗證模擬是否符合合約 * 可以呼叫 OrderServiceProxy 模擬真正的呼叫 * shouldVerifyExistingCustomer()模擬成功呼叫 * shouldFailToFindMissingOrder()模擬呼叫失敗 ### 10.1.3 針對 publish/subscribe-style interactions 的整合測試 * 會有服務發佈 domain events 也會有服務關注 * 像是Order相關的events是在有創建或是更新訂單的時候會發佈,而Order History Service會訂閱 * 需要驗證互動是不是正確的  * consumer-side 測試驗證OrderHistoryEventHandlers是否使用合約中的範例events * provider-side 測試驗證OrderDomainEventPublisher是否發布了確認合同的事件 * 發佈訂單事件的合約  * label — consumer 使用它來觸發Spring Contact發布事件 * triggeredBy — 測試的時候會被呼叫的方法 * provider-side test for Order Servic   * MessagingBase * 負責配置 OrderDomainEventPublisher 讓他使用 in-memory messaging stubs * orderCreated() * 被合約呼叫來觸發以及驗證事件是否符合合約 * consumer-side   * 先配置好會需要用到的模擬 * shouldHandleOrderCreatedEvent() * 會先呼叫Spring Cloud發佈事件 * stubFinder.trigger("orderCreatedEvent"); * 收到事件後再去驗證接下來的動作是否正確 * 像是呼叫OrderHistoryDao更新CQRS view ### 10.1.4 針對非同步request/response style interactions的整合測試 * Order Service 使用 sagas會將command messages 發送到其他服務,然後等待處理回來的訊息 * 這些回覆需要遵守 command message channel 的名稱跟回覆command 的架構 * 跟測試REST interactions蠻像的,HTTP變成但input message跟output message *  * KitchenServiceProxyTest 測試驗證 * provider-side 測試驗證 KitchenServiceCommandHandler 處理commands 並回覆 * consumer-side 測試驗證 KitchenServiceProxy 發送合約指定的 commands 處理合約的回覆 * 非同步 REQUEST/RESPONSE 合約  * 合約是從provider的觀點去寫的 在這就是kitchenService * 兩種 messages 都有指定 * message channel * message body * message headers * input message 的 CreateTicket command 是發送到 kitchenService channel * output message 是回覆到 CreateOrderSaga’s reply channel * CONSUMER-SIDE 的非同步 REQUEST/RESPONSE INTERACTION 合約整合測試  * Spring Cloud Contract會配置好KitchenServiceProxy模擬KitchenService * shouldSuccessfullyCreateTicket() * 發送CreateTicket 並驗證 * PROVIDER-SIDE 的非同步 REQUEST/RESPONSE INTERACTION 合約整合測試   * AbstractKitchenServiceConsumerContractTest class * KitchenServiceCommandHandler使用模擬的KitchenService ## 10.2 寫部件試驗測試 * component tests * 驗證一整個服務的流程 像是Order Service * 可以獨立驗證服務的行為 * Domain-Specific Languages (DSL) * Gherkin 來寫 acceptance tests(驗收測試)  ### 10.2.1 定義驗收測試 * 驗收測試是針對軟體部件的面向業務的測試(更實際) * 它們從客戶的觀點描述所需要的行為 * 這些測試來自客戶故事或例子 * 像是Order Service的故事 - Place Order 故事 * 每個 scenario 定義一個驗收測試 * givens - 測試的設置階段 * when - 執行的句子 * then 跟 and - 驗證的句子 >  * 上面描述做的事情 * Creates an Order by invoking the POST /orders endpoint * Verifies the state of the Order by invoking the GET /orders/{orderId} endpoint * Verifies that the Order Service published an OrderAuthorized event by subscribing to the appropriate message channel > 可以用來轉換成Java的程式碼 但上面的描述不夠好 用Gherkin更好 ### 10.2.2 使用Gherkin寫驗收測試 * 寫驗收測試可能 * 高階的描述跟低階的Java實作有脫節 * 模稜兩可轉換不成Java * Gherkin是用於寫可執行specifications的DSL * English-like scenarios * 用Cucumber執行specifications * Gherkin裡自動測試的框架 * feature - 很多的情境描數 * scenario - given-when-then架構 * givens - 前提條件 * when - 發生的動作或事件 * then/and - 預期的結果 * Order Service的範例用到下訂單、取消訂單、修改訂單 * Name - 下訂單 * pecification brief - 用戶故事的簡介 * Scenarios - 訂單被授權 跟 因為信用卡過期訂單被拒絕  * EXECUTING GHERKIN SPECIFICATIONS USING CUCUMBER * stepDefinition class * 寫著你的每個步驟  * @Given - The setup phase * @When - The execute phase * @Then ,@And - The verification phase ### 10.2.3 設計部件測試 * in-process component tests * in-memory stubs and mocks for its dependencie * out-process component tests * production-ready format and run it as a separate process ### 10.2.4 為FTGO的Order Service寫部件測試  * The OrderServiceComponentTestStepDefinitions class * usingCreditCard()   * placeOrder()  * theOrderShouldBe()  * verifyEventPublished()   * RUNNING THE COMPONENT TESTS * 把程式碼放到src/component-test/java * 執行./gradlew componentTest * 從ftgo-order-service/build.gradle Gradle的配置 * 用Docker運行Order Servic ## 10.3 端到端測試 * slow, brittle, and time consuming to develop * 因為要用到的服務粉多一個壞了就GG 能少測就少測  ### 10.3.1 設計端到端測試 * user journey test * 一次寫好會用到的功能一次測 * 像是創建訂單 修改訂單 取消訂單 ### 10.3.2 寫端到端測試 * 也是用Gherkin跟Cucumber  ### 10.3.3 運行端到端測試 * Gradle Docker Compose plugin 提供方便的方法,可以一次運行所有服務 * end-to-end tests跟component tests很像也是用Gherkin跟Cucumber * 但會著container越來越多,測試越來越多,時間會越來越長 * 還是做好金字塔下面的測試 ## Summary * 用consumer-driven contract來做測試 * component tests 透過API來測試服務 * user journey tests 縮小 end-to-end tests
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up