fluent_assertions/assertions/
mod.rs1use std::fmt::Debug;
2
3pub mod bool_assertion;
4pub mod collection_assertion;
5pub mod error_assertion;
6pub mod numeric_assertion;
7pub mod option_assertion;
8pub mod result_assertion;
9pub mod string_assertion;
10
11pub use collection_assertion::CollectionAssertion;
12pub use option_assertion::OptionAssertion;
13
14pub trait Should: Sized {
16 #[must_use = "this creates an assertion but checks nothing — call an assertion method like `.be(...)`"]
17 fn should(self) -> Assertion<Self>;
18}
19
20impl<T> Should for T {
24 fn should(self) -> Assertion<Self> {
25 Assertion { value: self }
26 }
27}
28
29pub struct Assertion<T> {
31 value: T,
32}
33
34impl<T> Assertion<T> {
35 pub fn into_inner(self) -> T {
46 self.value
47 }
48}
49
50impl<T> Assertion<T>
52where
53 T: Debug,
54{
55 #[track_caller]
64 pub fn be<U: Debug>(self, other: U) -> Self
65 where
66 T: PartialEq<U>,
67 {
68 assert!(
69 self.value == other,
70 "Expected value to be {:?}, but got {:?}",
71 other,
72 self.value
73 );
74 self
75 }
76
77 #[track_caller]
86 pub fn not_be<U: Debug>(self, other: U) -> Self
87 where
88 T: PartialEq<U>,
89 {
90 assert!(
91 self.value != other,
92 "Expected value to not be {:?}, but got {:?}",
93 other,
94 self.value
95 );
96 self
97 }
98}
99
100#[cfg(test)]
101mod tests {
102 use crate::assertions::*;
103
104 #[test]
105 fn be_allows_cross_type_comparison() {
106 "foo".to_string().should().be("foo");
107 }
108
109 #[test]
110 fn be_allows_debug_only_types() {
111 Some(5).should().be(Some(5));
112 }
113
114 #[test]
115 fn into_inner_returns_wrapped_value() {
116 let v = Some(5).should().be_some().into_inner();
117 assert_eq!(v, 5);
118 }
119}