目錄
- 前言
- 1. 微服務架構中的測驗策略概述
- 1.1 撰寫自動化測驗
- 1.2 使用模擬和樁進行測驗
- 1.3 使用范圍對測驗進行分類
- 1.4 使用測驗象限對測驗進行分類
- 1.5 使用測驗金字塔對測驗進行分類
- 1.6 微服務架構中的測驗挑戰
- 1.7 消費者驅動的契約測驗
- 1.8 使用Spring Cloud的契約測驗服務
- 1.9 部署流水線
- 2. 為服務撰寫單元測驗
- 2.1 兩種型別的單元測驗
- 2.2 類的職責決定使用哪種單元測驗
- 2.3 為物體撰寫單元測驗
- 2.4 為值物件撰寫單元測驗
- 2.5 為Saga撰寫單元測驗
- 2.6 為領域服務撰寫單元測驗
- 2.7 為控制器撰寫單元測驗
- 2.8 為事件和訊息處理程式撰寫單元測驗
- 3. 本章小結
- 最后
前言
傳統測驗在微服務架構中有兩大缺點:手動測驗效率極低、在交付流程中才進行測驗為時已晚;應該采取新的測驗策略提高微服務架構的可測驗性;
進行自動化測驗是縮短交付周期的唯一方法;
這是一本關于微服務架構設計方面的書,這是本人閱讀的學習筆記,以下對一些符號做些說明:
()為補充,一般是書本里的內容;
[]符號為筆者筆注;
1. 微服務架構中的測驗策略概述
本章重點在用于驗證應用程式或服務的功能的自動化測驗;
1.1 撰寫自動化測驗

圖解:
- 自動化測驗通常使用測驗框架撰寫,如JUnit;
- 自動化測驗通常包括四個階段:設定環境、執行測驗、驗證結果、清理環境;
- 清理環境很容易被忽略,在涉及資料庫的測驗可能需要在測驗后將資料庫狀態回滾到設定環境階段的初始狀態;
- 測驗套件是一組測驗類的集合,測驗由測驗運行器執行;
1.2 使用模擬和樁進行測驗
用來解決被測系統與其他系統之間的一些麻煩依賴關系;

圖解:
- 使用測驗替身來消除被測系統的依賴性;
- 測驗替身是一個物件,該物件負責模擬依賴項的行為;
- 有兩種型別的測驗替身:樁(stub)和模擬(mock)
- 樁是一個測驗替身,它代表依賴項來向被測系統發送呼叫的回傳值;
- 模擬也是一個測驗替身,用來驗證被測系統是否正確呼叫依賴項;此外,模擬通常也扮演樁的角色;
1.3 使用范圍對測驗進行分類
- 單元測驗:測驗服務的一小部分,如類;
- 集成測驗:驗證服務是否可以與基礎設施服務(如資料庫)或其他應用程式服務進行互動;
- 組件測驗:單個服務的驗收測驗;
- 端到端測驗:整個應用程式的驗收測驗;
1.4 使用測驗象限對測驗進行分類

圖解
- 兩個維度:
- 測驗是面向業務還是面向技術:使用領域專家的術語來描述面向業務的測驗,使用開發人員的術語和實作來描述面向技術的測驗;
- 測驗的目標是協助開發還是尋找產品缺陷:開發人員使用協助開發的測驗作為日常作業的一部分;尋找產品缺陷的測驗旨在確定需要改進的部分;
- 四種不同測驗類別:
- Q1協助開發 / 面向技術:單元和集成測驗;
- Q2協助開發 / 面向業務:組件和端到端測驗;
- Q3尋找產品缺陷 / 面向業務:易用性和探索性測驗;
- Q4尋找產品缺陷 / 面向技術:非功能性驗收測驗,如性能測驗;
1.5 使用測驗金字塔對測驗進行分類

圖解:
- 測驗范圍越大,其構成部件越多,可靠性越低;
- 強調要對服務的每一個細分元素進行測驗,能最大限度地減少測驗整個服務的組件測驗數量;
1.6 微服務架構中的測驗挑戰
行程通信是微服務架構的核心,應用程式模塊之間的任何互動都是通過編程語言級別的API進行的;因此測驗驗證API的服務是否能與其依賴關系和客戶端進行正常互動尤為重要;

圖解:
- 圖中的行程間通信方式:
- REST客戶端 - 服務端:API Gateway將請求路由到服務并實作API組合;
- 領域事件使用者 - 發布者:Order History Service使用Order Service發布的事件;
- 命令式訊息請求方 - 回復方:Order Service將命令式訊息發送到各種服務并使用回復;
- 一對服務之間的互動代表了這兩個服務之間的契約或協議,契約要求雙方就事件訊息結構及其發布的通道達成一致;
- 作為開發人員,需要確保服務具有穩定的API,做出的改動盡量不要破壞原有的API;
- 測驗兩個服務可以互動的一種方法是同時運行兩個服務,呼叫觸發通信的API,并驗證是否有預期結果;這會遇到集成的問題,解決方案是消費者驅動的契約測驗;
1.7 消費者驅動的契約測驗

圖解:
- 消費者驅動的契約測驗模式:驗證服務是否滿足它的消費者期望;
- 消費者契約測驗模式:驗證服務的客戶端是否可以與服務通信;
- 消費者驅動的契約測驗通常使用樣例測驗,消費者和提供者之間的互動由一組樣例定義,稱為契約;每個契約都包含在一次互動期間交換的樣例訊息;
- 消費者契約測驗側重于驗證提供者API的引數定義是否符合消費者的期望;
- 對于REST介面,契約測驗將驗證提供者程式實作的介面是否:
- 具有預期的HTTP方法和路徑;
- 接受預期的HTTP頭部;
- 接受請求主體;
- 回傳預期中的回應,包括狀態代碼、頭部和主體等;
- REST API的消費者契約測驗實際上是通過模擬控制器進行的測驗;
1.8 使用Spring Cloud的契約測驗服務

圖解:
- API Gateway團隊(消費者)撰寫的契約定義API Gateway如何與Order Service進行互動;
- 撰寫的契約包括API Gateway可能發送給Order Service的HTTP請求和預期的HTTP回應;
- Order Service團隊(提供者)使用這些契約來測驗Order Service,并使用它們來測驗API Gateway;測驗代碼Spring Cloud Contract生成;
- Order Service團隊(提供者)將測驗Order Service的契約打包成jar包發布到Maven存盤庫;
- API Gateway團隊(消費者)使用已發布的契約為API Gateway撰寫測驗;

- 一個契約示例;
- 請求元素是REST介面 GET/orders/{ orderId } 的一個HTTP請求;
- 回應元素是一個該介面對應的HTTP回應,它描述了API Gateway所期望的Order;
1.9 部署流水線

圖解:
- 其包含一系列執行測驗套件的階段,后面是一個發布或部署服務的階段;
- 理想情況下流水線是完全自動化的,也可能包含手動步驟;
- 部署流水線包含以下幾個階段:
- 提交前測驗階段:執行單元測驗,這是由開發人員在提交代碼更改之前執行的;
- 提交測驗階段:編譯服務,執行單元測驗,并執行靜態代碼分析;
- 集成測驗階段:執行集成測驗;
- 部署階段:將服務部署到生產環境中;
2. 為服務撰寫單元測驗
2.1 兩種型別的單元測驗

圖解:
- 獨立型單元測驗:使用針對類的依賴性的模擬物件隔離測驗;
- 協作型單元測驗:測驗一個類及其依賴項;
2.2 類的職責決定使用哪種單元測驗

圖解:
- 每個類的典型策略如下的:
- Order等具有持久化身份物件的物體,使用協作型單元測驗;
- Money等作為值集合物件的物體,使用協作型單元測驗;
- Sages等需要維護服務之間的資料一致性,使用協作型單元測驗;
- OrderService等實作不屬于物體或值物件的業務邏輯的類,使用獨立型單元測驗;
- OrderController等處理HTTP請求的控制器類,使用獨立型單元測驗;
- 入站和出站等訊息網關,使用獨立型測驗;
2.3 為物體撰寫單元測驗

- 單元測驗可以徹底測驗業務邏輯;
2.4 為值物件撰寫單元測驗

- 對值物件的測驗通常會創建特定狀態的值物件,呼叫其中一個方法,并對回傳值進行斷言;
- 這里使用獨立型單元測驗,因為此時Money類沒有任何依賴;前文說使用協作型單元測驗,是針對FTGO中Money物件的實際情況;
2.5 為Saga撰寫單元測驗

- Saga會實作重要的業務邏輯,其是一個持久化物件,向Saga參與方發送命令式訊息并處理他們的回復;
- 對Saga的測驗除了要為正常執行的場景撰寫測驗單元,還必須為Saga回滾的各種場景撰寫測驗;
- 一種方法是撰寫使用真實資料庫和訊息代理以及樁服務的測驗,以此來模擬各種Saga參與方;這種測驗非常緩慢;
- 一種更有效的方法是撰寫模型與資料庫和訊息代理互動的類的測驗;這樣可以專注測驗Saga的核心職責;
- 上述代碼使用Eventuate Tram Saga測驗框架撰寫,框架提供一個易于使用的DSL,其抽象出于Saga相互作用的細節;
- DSL可以創建一個Saga并驗證其是否發出正確的訊息;
- 事實上,Saga測驗框架使用資料庫和訊息傳遞基礎設施的模擬來配置Saga框架;
2.6 為領域服務撰寫單元測驗


- 服務的大多數業務邏輯通過物體類、值物件和Saga實作;領域服務類實作業務邏輯的其余部分;
- 測驗領域服務類使用獨立型單元測驗,它可以模擬儲存庫和訊息傳遞類等依賴項;
- 每個測驗按如下方法完成各自測驗階段:
- 設定:配置服務依賴項的模擬物件;
- 執行:呼叫服務方法;
- 驗證:驗證服務方法回傳的值是否正確,以及是否已正確呼叫依賴項;
2.7 為控制器撰寫單元測驗


- 服務類通常具有一個或多個控制器,用于處理來自其他服務和API Gateway的HTTP請求;
- 控制器類由一組請求處理程式方法組成,每個方法實作一個REST API端點;
- 使用某些框架,如Spring Mock Mvc撰寫的測驗會產生模擬的HTTP請求,并對HTTP回應進行斷言;
- 這些框架在測驗HTTP請求路由以及Java物件與JSON之間的轉換時,無須進行真正的網路呼叫;
- 上述代碼是一個獨立單元測驗,利用模擬物件來解決OrderController的依賴項;
- 上述代碼使用REST Assured Mock MVC撰寫,提供一個DSL,抽象出與控制器互動的細節;其可以輕松地模擬HTTP請求發送到控制器并驗證回應;
2.8 為事件和訊息處理程式撰寫單元測驗

- 與控制器類似,訊息配接器往往是呼叫領域服務的簡單類,因此可以使用類似針對控制器進行單元測驗的方法;
- 每個測驗示例都是訊息配接器,向訊息通道發送訊息,并驗證是否正確呼叫了服務模擬;
- 使用Eventuate Tram Mock Messaging框架進行測驗,框架提供了一個易于使用的DSL,用于撰寫模擬訊息測驗;
- 為了驗證服務是否與正確地與其他服務互動,必須撰寫集成測驗;還需要撰寫單獨測驗整個服務的組件測驗;這點在下一章進行討論;
3. 本章小結
- 自動化測驗是快速、安全地互動軟體的重要基石,更重要的是,由于微服務架構固有的復雜性,要從微服務架構中充分受益,必須實作自動化測驗;
- 測驗的目的是驗證被測驗系統(SUT)的行為,在這個定義中,系統是一個泛指,意味著被測驗的軟體元素,它可能像一個類一樣小,也可能像整個應用程式一樣大,或者是介于兩者之間,例如一組類或一個單獨的服務,測驗套件是一組相關測驗的集合;
- 簡化和加快測驗的一個好方法是使用測驗替身,測驗替身是一個模擬被測系統依賴項的行為的物件,有兩種型別的測驗替身:樁和模擬,樁是一個測驗替身,它將值回傳給被測系統,模擬也是一個測驗替身,由測驗用來驗證被測系統是否正確呼叫依賴;
- 使用測驗金字塔可確定將測驗作業重點放在服務的哪個部分,大多數測驗應該是快速、可靠且易于撰寫的單元測驗,必須盡量減少端到端測驗的數量,因為它們寫入速度慢、脆弱且耗時;
最后

轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/308440.html
標籤:架構設計
上一篇:微服務拆分原則以及實踐
下一篇:負載均衡在web系統中的應用
