Skip to main content

ddd_toolkit_core/mock/
id.rs

1use crate::{domain::EntityId, port::id::IdGenerator};
2
3/// An [`IdGenerator`] that always returns the same, fixed id.
4///
5/// # Examples
6///
7/// ```
8/// use ddd_toolkit_core::domain::{EntityId, ValueObject};
9/// use ddd_toolkit_core::mock::id::FixedIdGenerator;
10/// use ddd_toolkit_core::port::id::IdGenerator;
11/// use std::fmt::Display;
12///
13/// #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
14/// struct OrderId(u32);
15///
16/// impl ValueObject for OrderId {}
17///
18/// impl Display for OrderId {
19///     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20///         write!(f, "order-{}", self.0)
21///     }
22/// }
23///
24/// impl EntityId for OrderId {}
25///
26/// // useful in a test that needs a predictable id to assert against
27/// let generator = FixedIdGenerator(OrderId(1));
28///
29/// assert_eq!(generator.generate(), OrderId(1));
30/// assert_eq!(generator.generate(), OrderId(1));
31/// ```
32#[derive(Debug, Clone)]
33pub struct FixedIdGenerator<Id>(pub Id);
34
35impl<Id: EntityId> IdGenerator<Id> for FixedIdGenerator<Id> {
36    fn generate(&self) -> Id {
37        self.0.clone()
38    }
39}
40
41#[cfg(test)]
42mod test {
43    use std::fmt::Display;
44
45    use crate::domain::ValueObject;
46
47    use super::*;
48
49    #[derive(Debug, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]
50    struct FooId(String);
51
52    impl ValueObject for FooId {}
53
54    impl Display for FooId {
55        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56            write!(f, "{}", self.0)
57        }
58    }
59
60    impl EntityId for FooId {}
61
62    #[test]
63    fn generate_returns_the_fixed_id() {
64        let generator = FixedIdGenerator(FooId("id-1".to_string()));
65
66        assert_eq!(generator.generate(), FooId("id-1".to_string()));
67    }
68
69    #[test]
70    fn generate_returns_equal_id_on_repeated_calls() {
71        let generator = FixedIdGenerator(FooId("id-1".to_string()));
72
73        assert_eq!(generator.generate(), FooId("id-1".to_string()));
74        assert_eq!(generator.generate(), FooId("id-1".to_string()));
75        assert_eq!(generator.generate(), FooId("id-1".to_string()));
76    }
77
78    #[test]
79    fn inner_field_is_publicly_accessible() {
80        let mut generator = FixedIdGenerator(FooId("id-1".to_string()));
81
82        assert_eq!(generator.0, FooId("id-1".to_string()));
83
84        generator.0 = FooId("id-2".to_string());
85
86        assert_eq!(generator.generate(), FooId("id-2".to_string()));
87    }
88
89    #[test]
90    fn clone_produces_generator_returning_equal_id() {
91        let generator = FixedIdGenerator(FooId("id-1".to_string()));
92
93        let cloned = generator.clone();
94
95        assert_eq!(cloned.generate(), generator.generate());
96    }
97
98    #[test]
99    fn debug_format_contains_type_name_and_inner_id() {
100        let generator = FixedIdGenerator(FooId("id-1".to_string()));
101
102        let debug = format!("{generator:?}");
103
104        assert!(debug.contains("FixedIdGenerator"));
105        assert!(debug.contains("id-1"));
106    }
107
108    #[test]
109    fn box_dyn_id_generator_is_usable() {
110        let generator: Box<dyn IdGenerator<FooId>> =
111            Box::new(FixedIdGenerator(FooId("id-1".to_string())));
112
113        assert_eq!(generator.generate(), FooId("id-1".to_string()));
114    }
115
116    #[test]
117    fn generate_returns_id_with_empty_inner_value_as_is() {
118        let generator = FixedIdGenerator(FooId(String::new()));
119
120        assert_eq!(generator.generate(), FooId(String::new()));
121    }
122}