尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

Rust事件溯源测试清单:用eventually-rs的given-when-then Scenario测试聚合根

Rust事件溯源测试清单:用eventually-rs的given-when-then Scenario测试聚合根 Rust事件溯源测试清单用eventually-rs的given-when-then Scenario测试聚合根【免费下载链接】eventually-rsEvent Sourcing for Rust项目地址: https://gitcode.com/gh_mirrors/ev/eventually-rseventually-rs 是 Rust 生态中用于构建事件溯源Event Sourcing应用的核心库它不仅提供了聚合根Aggregate Root与事件存储的抽象还内置了Scenario测试类型——让你用经典的given-when-then三段式画布快速、清晰地测试聚合根的行为。本文是一份实战清单帮你在 Rust 项目中快速上手这套事件溯源测试方法。一、30秒背景事件溯源与聚合根事件溯源系统不保存数据的当前状态而是把所有变更按顺序存为不可变事件当前状态由事件日志回放rehydrate得出。在 eventually-rs 中Aggregate聚合领域模型状态只能通过领域事件变更核心定义见eventually/src/aggregate/mod.rsRoot聚合根的运行时载体负责记录未提交事件、跟踪版本号Scenario专测聚合根行为的测试类型位于eventually/src/aggregate/test.rs 理解这三者就理解了整个测试框架Scenario 会用 given 的事件回放出一个 Root执行 when 中的操作再断言产生的事件是否符合预期。二、核心工具Scenario 三段式测试Scenario::new()开启一个场景链式调用即可读性极强Scenario::MyAggregate::new() .given(vec![...]) // 前置条件已有事件 .when(|root| { ... }) // 执行动作调用聚合根方法 .then(vec![...]) // 期望结果应产生哪些事件 .assert(); // 执行并断言前置条件given —— 事件列表回放状态given接收一组领域事件Scenario 会自动将其折叠fold成聚合根的当前状态。这正好利用了事件溯源的本质状态 事件历史。执行动作when —— 两种分支分支适用场景闭包签名Scenario::when创建全新聚合根无历史事件Fn() - ResultR, ErrScenarioGiven::when修改已存在的聚合根Fn(mut R) - Result(), Err⚠️ 注意given(...).when(...)分支如果给定事件无法成功回放出一个 Root会直接 panic 并让测试失败——这是有意设计防止测试前提本身出错。断言结果then / then_error / assert.then(events)断言操作成功后恰好产生这些事件.then_error(err)断言操作按预期失败并返回指定错误.assert()执行整个场景断言不通过则 panic 使测试失败这套设计让你既测快乐路径也测业务规则拒绝的路径。三、完整示例灯开关聚合根走一遍以官方 light-switch 示例为例领域模型见examples/light-switch/src/domain.rs聚合根暴露了install安装、turn_on开灯、turn_off关灯等操作并定义了AlreadyOn、NotYetInstalled等业务错误。一个典型的场景测试思路成功路径Scenario::LightSwitch::new() .given(vec![LightSwitchEvent::Installed(...).into()]) // 已安装 .when(|root| root.turn_on(id)) // 尝试开灯 .then(vec![LightSwitchEvent::SwitchedOn(...).into()]) // 应产生开灯事件 .assert();失败路径同样简单Scenario::LightSwitch::new() .given(vec![已安装, 已开灯 两个事件]) .when(|root| root.turn_on(id)) .then_error(LightSwitchError::AlreadyOn) // 已经开着了 .assert(); 两段代码就完整覆盖了开灯成功和重复开灯被拒两条业务规则无需 mock、无需数据库。四、进阶命令级 Scenariocommand::test::Scenario当你要测试的是命令处理器Command Handler而不仅仅是聚合根时eventually-rs 在eventually/src/command/test.rs提供了另一套 Scenariocommand::test::Scenario .given(vec![已持久化的事件]) // 系统前置状态 .when(命令.into()) // 直接投递命令 .then(vec![期望持久化的事件]) // 或 .then_fails() .assert_on(|event_store| Service::from(repo)) .await;它与聚合级 Scenario 的关键区别given 用的是event::Persisted含 stream_id 和 version描述事件存储中的真实数据then_fails只断言失败不指定具体错误assert_on注入一个内存事件存储构建被测服务测试在真实但内存中的存储上跑完整链路银行记账示例examples/bank-accounting/src/application.rs里就有一组完整示范开户成功、重复开户失败、向已关闭账户存款失败、转账余额不足失败……每个场景一个测试函数命名即文档。五、实战清单写 Event Sourcing 测试前对照每个业务不变量至少对应一个then_error场景如不能重复安装每个领域事件都有一条成功路径的then断言用given覆盖状态机边界初始态、中间态、终态聚合级用aggregate::test::Scenario应用级用command::test::Scenario测试命名遵循场景_条件_结果句式参考 bank-accounting 的测试函数命名需要持久化行为时用内存事件存储eventually/src/event/store.rs或 PostgreSQL 实现eventually-postgres六、关键文件导航文件路径作用eventually/src/aggregate/mod.rsAggregate trait 与 Root 实现eventually/src/aggregate/test.rs聚合级 given-when-then Scenarioeventually/src/command/test.rs命令级 Scenariothen_fails / assert_oneventually/src/event/store.rs事件存储抽象与内存实现examples/light-switch/src/domain.rs最简聚合根领域模型示例examples/bank-accounting/src/application.rs命令级场景测试完整示范按照这份清单你的 Rust 事件溯源测试将同时做到可读given-when-then 即业务语言、可信成功与失败路径双覆盖、可维护每个场景独立、命名即文档。【免费下载链接】eventually-rsEvent Sourcing for Rust项目地址: https://gitcode.com/gh_mirrors/ev/eventually-rs创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表