ddd_toolkit_core/domain/
error.rs1use std::{error::Error, fmt::Display};
2
3#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct ValidationError {
15 pub type_name: &'static str,
17 pub reason: String,
19}
20
21impl ValidationError {
22 pub fn new(type_name: &'static str, reason: impl Into<String>) -> Self {
24 Self {
25 type_name,
26 reason: reason.into(),
27 }
28 }
29}
30
31impl Display for ValidationError {
32 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
33 write!(f, "invalid {}: {}", self.type_name, self.reason)
34 }
35}
36
37impl Error for ValidationError {}
38
39#[cfg(test)]
40mod test {
41 use crate::domain::ValidationError;
42
43 #[test]
44 fn new_sets_type_name_field() {
45 let ve = ValidationError::new("foo", "bar");
46 assert_eq!(ve.type_name, "foo")
47 }
48
49 #[test]
50 fn new_sets_reason_field() {
51 let ve = ValidationError::new("foo", "bar");
52 assert_eq!(ve.reason, "bar")
53 }
54
55 #[test]
56 fn new_accepts_str_reason() {
57 ValidationError::new("foo", "bar");
58 }
59
60 #[test]
61 fn new_accepts_string_reason() {
62 ValidationError::new("foo", "bar".to_string());
63 }
64
65 #[test]
66 fn display_formats_invalid_type_and_reason() {
67 let ve = ValidationError::new("foo", "bar");
68 assert_eq!(format!("{ve}"), "invalid foo: bar")
69 }
70
71 #[test]
72 fn clone_produces_equal_value() {
73 let ve = ValidationError::new("foo", "bar");
74 let ve_clone = ve.clone();
75
76 assert_eq!(ve, ve_clone);
77 assert_eq!(ve.type_name, ve_clone.type_name);
78 assert_eq!(ve.reason, ve_clone.reason)
79 }
80
81 #[test]
82 fn eq_returns_true_for_same_fields() {
83 let ve = ValidationError::new("foo", "bar");
84 let ve_2 = ValidationError::new("foo", "bar");
85
86 assert_eq!(ve, ve_2);
87 assert_eq!(ve.type_name, ve_2.type_name);
88 assert_eq!(ve.reason, ve_2.reason)
89 }
90
91 #[test]
92 fn eq_returns_false_for_different_type_name() {
93 let ve = ValidationError::new("foo", "bar");
94 let ve_2 = ValidationError::new("bar", "bar");
95
96 assert_ne!(ve, ve_2);
97 assert_ne!(ve.type_name, ve_2.type_name);
98 assert_eq!(ve.reason, ve_2.reason)
99 }
100
101 #[test]
102 fn eq_returns_false_for_different_reason() {
103 let ve = ValidationError::new("foo", "bar");
104 let ve_2 = ValidationError::new("foo", "foo");
105
106 assert_ne!(ve, ve_2);
107 assert_eq!(ve.type_name, ve_2.type_name);
108 assert_ne!(ve.reason, ve_2.reason)
109 }
110
111 #[test]
112 fn implements_std_error_trait() {
113 let ve = ValidationError::new("foo", "bar");
114 let err: &dyn std::error::Error = &ve;
115 assert!(err.source().is_none())
116 }
117
118 #[test]
119 fn new_accepts_empty_reason() {
120 let ve = ValidationError::new("foo", "");
121 assert!(ve.reason.is_empty())
122 }
123
124 #[test]
125 fn display_formats_empty_reason() {
126 let ve: ValidationError = ValidationError::new("foo", "");
127 assert_eq!(format!("{}", ve), "invalid foo: ")
128 }
129}