當前位置:編程學習大全網 - 源碼下載 - Axon Framework - 命令和事件測試

Axon Framework - 命令和事件測試

CQRS 的好處之壹,尤其是事件溯源的好處之壹,是可以純粹根據事件和命令來表達測試。 作為功能組件、事件和命令,對於領域專家或業務所有者來說,它們都具有明確的意義。 這不僅意味著以事件和命令表示的測試具有明確的功能意義,還意味著它們幾乎不依賴於任何實現選擇。

本文介紹的功能需要 axon-test 模塊,可以通過配置 maven 依賴獲得(使用 axon-test 和 test ) 或從完整包下載。

本文章中描述的套件適用於任何測試框架,例如 JUnit 和 TestNG 。

命令處理組件通常是任何基於 CQRS 的架構中包含最復雜的組件。 比其他組件更復雜,這也意味著該組件有額外的測試相關要求。

雖然更復雜,但命令處理組件的 API 相當簡單。 它有壹個命令進來,事件出去。 在某些情況下,可能會有查詢作為命令執行的壹部分。 除此之外,命令和事件是 API 的壹部分。 這意味著可以根據事件和命令完全定義測試場景。 通常,呈以下形狀:

Axon Framework 提供了壹個測試套件,可以讓您完全做到這壹點。 AggregateTestFixture 允許您配置特定的基礎設施,由必要的命令處理程序和倉儲組成,並用 “given-when-then” 事件和命令來表達您的場景。

測試套件的關註點

由於這裏的測試單元是聚合,所以 AggregateTestFixture 僅用於測試壹個聚合。 因此, when (或`given`)子句中的所有命令都旨在針對測試套件下的聚合。 此外,所有 given 和 expected 事件都應該從被測套件的聚合中觸發。

以下示例顯示了在 GiftCard 聚合(如前所述)上使用 JUnit 4 的 “given-when-then” 測試套件:

聚合生命周期擴展

或者,JUnit 5 用戶可以使用 StubAggregateLifecycleExtension 直接附加到聚合生命周期。 如果您不想使用 AggregateTestFixture ,這可能很有用

“given-when-then” 測試套件定義了三個階段:配置、執行和驗證。 這些階段中的每壹個都由不同的接口表示:分別是 FixtureConfiguration 、 TestExecutor 和 ResultValidator 。

流暢的接口

為了充分利用這些階段之間的遷移,最好使用這些方法提供的流暢接口,如上例所示。

在配置階段(即在提供第壹個 "given" 之前),您提供執行測試所需的構建塊。 默認情況下,事件總線、命令總線和事件存儲的專用版本作為套件的壹部分提供。 有壹些訪問器方法可以獲取對它們的引用。 任何未直接在聚合上註冊的命令處理程序都需要使用 registerAnnotatedCommandHandler 方法進行顯式配置。 除了帶註解的命令處理程序之外,您還可以註冊各種組件和設置,這些組件和設置定義了應如何設置圍繞聚合測試的基礎設施,包括以下內容:

壹旦配置了套件,您就可以定義 "given" 事件。 測試套件會將這些事件包裝為 DomainEventMessage 。 如果 "given" 事件實現了 Message ,則該消息的有效負載和元數據將包含在 DomainEventMessage 中,否則將給定事件用作有效負載。 DomainEventMessage 的序列號是連續的,從 “0” 開始。 如果沒有預期的先前活動,則可以使用 givenNoPriorActivity() 作為起點。

或者,您也可以提供命令作為 "given" 場景。 在這種情況下,這些命令生成的事件將用於在執行實際測試命令時為聚合提供事件源。 使用 givenCommands(…) 方法提供命令對象。

"given" 階段的最後壹個選項是直接提供聚合的狀態。 在事件溯源的情況下不建議這樣做,並且僅在基於命令或事件重建聚合不可行或使用狀態存儲聚合的情況下才建議這樣做。 使用 fixture.givenState) new GiftCard( 來定義初始狀態。

執行階段允許您進入驗證階段的兩個入口點。 首先,您可以提供要針對命令處理組件執行的命令。 與給定事件類似,如果提供的命令是 CommandMessage 類型,它將按原樣分派。 調用的處理程序的行為(在聚合上或作為外部處理程序)被監視並與在驗證階段註冊的期望進行比較。

其次,可以使用 whenThenTimeElapses(Duration) 和 whenThenTimeAdvancesTo(Instant) 句柄來過去某個時間跨度。 這些支持測試 DeadlineMessages 的發布。

非法狀態變化檢測

在執行測試期間,Axon 嘗試檢測被測聚合體中的任何非法狀態變化。 它通過將命令執行後聚合的狀態與聚合的狀態進行比較來實現這壹點,如果聚合來自所有 "given" 和存儲的事件。 如果該狀態不相同,這意味著狀態更改發生在聚合的事件處理程序方法之外。 比較中忽略靜態和瞬態字段,因為它們通常包含對資源的引用。

您可以使用 setReportIllegalStateChange() 方法在套件配置中切換檢測。

最後壹個階段是驗證階段,它允許您檢查命令處理組件的活動。 這通常純粹根據返回值和事件來完成。

測試套件允許您驗證命令處理程序的返回值。 您可以顯式定義預期的返回值,或者只是要求方法成功返回。 您還可以表達您希望 CommandHandler 拋出的任何異常。

以下方法可用於驗證命令結果:

另壹個組件是對已發布事件的驗證。 有兩種匹配預期事件的方法。

第壹種是傳入需要與實際事件進行逐字比較的事件實例。 將預期事件的所有屬性與實際事件中的對應屬性進行比較(使用 equals() )。 如果其中壹個屬性不相等,則測試失敗並生成大量錯誤報告。

另壹種表達期望的方式是使用 Matchers (由 Hamcrest 庫提供)。 Matcher 是壹個接口,規定了兩種方法: matches(Object) 和 describeTo(Description) 。 第壹個返回壹個布爾值來指示匹配器是否匹配。 第二個讓妳表達妳的期望。 例如,“GreaterThanTwoMatcher” 可以將“ 任何值大於 2 的事件” 附加到描述中。 描述允許創建關於測試用例失敗原因的富有表現力的錯誤消息。

為事件列表創建匹配器可能是乏味且容易出錯的工作。 為了簡化事情,Axon 提供了壹組匹配器,允許您提供壹組特定於事件的匹配器,並告訴 Axon 它們應該如何匹配列表。 這些匹配器通過抽象的 Matchers 工具實用程序類靜態可用。

以下是可用事件列表匹配器及其用途的概述:

為方便起見,提供了壹些常用的事件匹配器。 它們與單個事件實例匹配:

由於匹配器傳遞的是事件消息列表,因此您有時只想驗證消息的有效負載。 有匹配器可以幫助您:

下面是壹個小代碼示例,展示了這些匹配器的用法。 在此示例中,我們期望發布兩個事件。 第壹個事件必須是 "ThirdEvent",第二個事件是 "aFourthEventWithSomeSpecialThings"。 可能沒有第三個事件,因為這將對 "andNoMore" 匹配器失敗。

在某些情況下,可能需要驗證測試後聚合的狀態。 在 given-when-then 場景中尤其如此,其中給定也表示初始狀態,這在使用 State-Stored Aggregate 時很常見。

套件提供了壹種方法,允許驗證聚合的狀態,因為它在執行階段之後(例如,when 狀態)被驗證。

expectState 方法采用 Aggregate 類型的使用者。 使用測試框架提供的常規斷言來斷言給定聚合的狀態。 任何(運行時)異常或錯誤都會相應地使測試用例失敗。

事件溯源聚合狀態驗證

測試事件溯源聚合的狀態驗證被認為是不好的做法。 理想情況下,聚合的狀態對測試代碼是完全不透明的,因為只有行為應該被驗證。 通常,驗證狀態的願望表明測試套件中缺少某個測試場景。

驗證階段還提供了驗證給定聚合實例的 scheduled 和滿足的 deadline 選項。 您可以通過 Duration 或 Instant 來預期預定的 deadline,使用顯式 equals 、 Matcher 或僅使用 deadline 類型來驗證 deadline 消息。

  • 上一篇:php數組怎麽添加壹個元素
  • 下一篇:格力雲控怎樣控制中央空調?急求
  • copyright 2024編程學習大全網