ddd_toolkit_core/domain/
aggregate.rs1use crate::domain::{DomainEvent, Entity};
2
3pub trait AggregateRoot: Entity {
7 type Event: DomainEvent;
9
10 fn record(&mut self, event: Self::Event);
13
14 fn take_events(&mut self) -> Vec<Self::Event>;
16}
17
18#[cfg(test)]
19mod test {
20 use std::fmt::Display;
21
22 use crate::domain::{EntityId, ValueObject};
23
24 use super::*;
25
26 #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
27 struct FooId(String);
28
29 impl ValueObject for FooId {}
30
31 impl Display for FooId {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 write!(f, "{}", self.0)
34 }
35 }
36
37 impl EntityId for FooId {}
38
39 #[derive(Debug, PartialEq)]
40 struct FooEvent {
41 name: String,
42 }
43
44 impl DomainEvent for FooEvent {}
45
46 fn event(name: &str) -> FooEvent {
47 FooEvent {
48 name: name.to_string(),
49 }
50 }
51
52 struct Foo {
53 id: FooId,
54 events: Vec<FooEvent>,
55 }
56
57 impl Foo {
58 fn new(id: &str) -> Self {
59 Self {
60 id: FooId(id.to_string()),
61 events: Vec::new(),
62 }
63 }
64 }
65
66 impl Entity for Foo {
67 type Id = FooId;
68
69 fn id(&self) -> &Self::Id {
70 &self.id
71 }
72 }
73
74 impl AggregateRoot for Foo {
75 type Event = FooEvent;
76
77 fn record(&mut self, event: Self::Event) {
78 self.events.push(event);
79 }
80
81 fn take_events(&mut self) -> Vec<Self::Event> {
82 std::mem::take(&mut self.events)
83 }
84 }
85
86 #[test]
87 fn record_single_event_take_events_returns_it() {
88 let mut foo = Foo::new("foo-1");
89
90 foo.record(event("created"));
91
92 assert_eq!(foo.take_events(), vec![event("created")]);
93 }
94
95 #[test]
96 fn record_multiple_events_take_events_returns_in_recorded_order() {
97 let mut foo = Foo::new("foo-1");
98
99 foo.record(event("created"));
100 foo.record(event("updated"));
101 foo.record(event("deleted"));
102
103 assert_eq!(
104 foo.take_events(),
105 vec![event("created"), event("updated"), event("deleted")]
106 );
107 }
108
109 #[test]
110 fn take_events_clears_recorded_events() {
111 let mut foo = Foo::new("foo-1");
112 foo.record(event("created"));
113
114 foo.take_events();
115
116 assert_eq!(foo.take_events(), vec![]);
117 }
118
119 #[test]
120 fn record_after_take_events_returns_only_new_events() {
121 let mut foo = Foo::new("foo-1");
122 foo.record(event("created"));
123 foo.take_events();
124
125 foo.record(event("updated"));
126
127 assert_eq!(foo.take_events(), vec![event("updated")]);
128 }
129
130 #[test]
131 fn aggregate_root_impl_satisfies_entity_supertrait() {
132 let a = Foo::new("foo-1");
133 let b = Foo::new("foo-1");
134 let c = Foo::new("foo-2");
135
136 assert_eq!(a.id(), &FooId("foo-1".to_string()));
137 assert!(a.is_same_as(&b));
138 assert!(!a.is_same_as(&c));
139 }
140
141 #[test]
142 fn aggregate_root_impl_satisfies_send_and_sync() {
143 fn assert_impl<T: Send + Sync>() {}
144 assert_impl::<Foo>();
145 }
146
147 #[test]
148 fn generic_fn_accepts_aggregate_root_impl() {
149 fn drain<T: AggregateRoot>(aggregate: &mut T, event: T::Event) -> Vec<T::Event> {
150 aggregate.record(event);
151 aggregate.take_events()
152 }
153
154 let mut foo = Foo::new("foo-1");
155
156 assert_eq!(drain(&mut foo, event("created")), vec![event("created")]);
157 }
158
159 #[test]
160 fn take_events_on_fresh_aggregate_returns_empty_vec() {
161 let mut foo = Foo::new("foo-1");
162
163 assert_eq!(foo.take_events(), vec![]);
164 }
165
166 #[test]
167 fn record_duplicate_events_are_both_returned() {
168 let mut foo = Foo::new("foo-1");
169
170 foo.record(event("created"));
171 foo.record(event("created"));
172
173 assert_eq!(foo.take_events(), vec![event("created"), event("created")]);
174 }
175}