ddd_toolkit_core/domain/
aggregate.rs1use crate::domain::{DomainEvent, Entity};
2
3pub trait AggregateRoot: Entity {
67 type Event: DomainEvent;
69
70 fn record(&mut self, event: Self::Event);
73
74 fn take_events(&mut self) -> Vec<Self::Event>;
76}
77
78#[cfg(test)]
79mod test {
80 use std::fmt::Display;
81
82 use crate::domain::{EntityId, ValueObject};
83
84 use super::*;
85
86 #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
87 struct FooId(String);
88
89 impl ValueObject for FooId {}
90
91 impl Display for FooId {
92 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
93 write!(f, "{}", self.0)
94 }
95 }
96
97 impl EntityId for FooId {}
98
99 #[derive(Debug, PartialEq)]
100 struct FooEvent {
101 name: String,
102 }
103
104 impl DomainEvent for FooEvent {}
105
106 fn event(name: &str) -> FooEvent {
107 FooEvent {
108 name: name.to_string(),
109 }
110 }
111
112 struct Foo {
113 id: FooId,
114 events: Vec<FooEvent>,
115 }
116
117 impl Foo {
118 fn new(id: &str) -> Self {
119 Self {
120 id: FooId(id.to_string()),
121 events: Vec::new(),
122 }
123 }
124 }
125
126 impl Entity for Foo {
127 type Id = FooId;
128
129 fn id(&self) -> &Self::Id {
130 &self.id
131 }
132 }
133
134 impl AggregateRoot for Foo {
135 type Event = FooEvent;
136
137 fn record(&mut self, event: Self::Event) {
138 self.events.push(event);
139 }
140
141 fn take_events(&mut self) -> Vec<Self::Event> {
142 std::mem::take(&mut self.events)
143 }
144 }
145
146 #[test]
147 fn record_single_event_take_events_returns_it() {
148 let mut foo = Foo::new("foo-1");
149
150 foo.record(event("created"));
151
152 assert_eq!(foo.take_events(), vec![event("created")]);
153 }
154
155 #[test]
156 fn record_multiple_events_take_events_returns_in_recorded_order() {
157 let mut foo = Foo::new("foo-1");
158
159 foo.record(event("created"));
160 foo.record(event("updated"));
161 foo.record(event("deleted"));
162
163 assert_eq!(
164 foo.take_events(),
165 vec![event("created"), event("updated"), event("deleted")]
166 );
167 }
168
169 #[test]
170 fn take_events_clears_recorded_events() {
171 let mut foo = Foo::new("foo-1");
172 foo.record(event("created"));
173
174 foo.take_events();
175
176 assert_eq!(foo.take_events(), vec![]);
177 }
178
179 #[test]
180 fn record_after_take_events_returns_only_new_events() {
181 let mut foo = Foo::new("foo-1");
182 foo.record(event("created"));
183 foo.take_events();
184
185 foo.record(event("updated"));
186
187 assert_eq!(foo.take_events(), vec![event("updated")]);
188 }
189
190 #[test]
191 fn aggregate_root_impl_satisfies_entity_supertrait() {
192 let a = Foo::new("foo-1");
193 let b = Foo::new("foo-1");
194 let c = Foo::new("foo-2");
195
196 assert_eq!(a.id(), &FooId("foo-1".to_string()));
197 assert!(a.is_same_as(&b));
198 assert!(!a.is_same_as(&c));
199 }
200
201 #[test]
202 fn aggregate_root_impl_satisfies_send_and_sync() {
203 fn assert_impl<T: Send + Sync>() {}
204 assert_impl::<Foo>();
205 }
206
207 #[test]
208 fn generic_fn_accepts_aggregate_root_impl() {
209 fn drain<T: AggregateRoot>(aggregate: &mut T, event: T::Event) -> Vec<T::Event> {
210 aggregate.record(event);
211 aggregate.take_events()
212 }
213
214 let mut foo = Foo::new("foo-1");
215
216 assert_eq!(drain(&mut foo, event("created")), vec![event("created")]);
217 }
218
219 #[test]
220 fn take_events_on_fresh_aggregate_returns_empty_vec() {
221 let mut foo = Foo::new("foo-1");
222
223 assert_eq!(foo.take_events(), vec![]);
224 }
225
226 #[test]
227 fn record_duplicate_events_are_both_returned() {
228 let mut foo = Foo::new("foo-1");
229
230 foo.record(event("created"));
231 foo.record(event("created"));
232
233 assert_eq!(foo.take_events(), vec![event("created"), event("created")]);
234 }
235}