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