Skip to main content

ddd_toolkit_core/domain/
aggregate.rs

1use crate::domain::{DomainEvent, Entity};
2
3/// An [`Entity`] that is a consistency boundary and the unit of persistence:
4/// changes to it (and whatever it contains) are saved and loaded together,
5/// and it records the domain events those changes produce.
6pub trait AggregateRoot: Entity {
7    /// The domain event type this aggregate records.
8    type Event: DomainEvent;
9
10    /// Records that `event` happened, to be drained later via
11    /// [`AggregateRoot::take_events`].
12    fn record(&mut self, event: Self::Event);
13
14    /// Returns and clears every event recorded since the last call.
15    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}