Skip to content

Commit 22866af

Browse files
committed
fix: implement assertions for Result for borrowed &Result as well
1 parent 60049e0 commit 22866af

3 files changed

Lines changed: 474 additions & 4 deletions

File tree

src/assertions.rs

Lines changed: 48 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1399,7 +1399,7 @@ pub trait AssertOption {
13991399
fn is_none(self) -> Self;
14001400
}
14011401

1402-
/// Assert the option value by mapping the subject.
1402+
/// Assert the value of an option by mapping the subject.
14031403
///
14041404
/// If the option is none, the assertion fails.
14051405
///
@@ -1433,7 +1433,7 @@ pub trait AssertOptionValue<'a, T, R> {
14331433
fn some(self) -> Spec<'a, T, R>;
14341434
}
14351435

1436-
/// Assert the borrowed option value by mapping the subject.
1436+
/// Assert the value of a borrowed option by mapping the subject.
14371437
///
14381438
/// If the option is none, the assertion fails.
14391439
///
@@ -1508,7 +1508,7 @@ pub trait AssertResult {
15081508
fn is_err(self) -> Self;
15091509
}
15101510

1511-
/// Assert the result value or error by mapping the subject.
1511+
/// Assert the ok-value or error of a result by mapping the subject.
15121512
///
15131513
/// # Examples
15141514
///
@@ -1553,6 +1553,51 @@ pub trait AssertResultValue<'a, T, E, R> {
15531553
fn err(self) -> Spec<'a, E, R>;
15541554
}
15551555

1556+
/// Assert the ok-value or error of a borrowed result by mapping the subject.
1557+
///
1558+
/// # Examples
1559+
///
1560+
/// ```
1561+
/// use asserting::prelude::*;
1562+
///
1563+
/// let subject: Result<Vec<usize>, String> = Ok(vec![1, 2, 3]);
1564+
/// assert_that!(&subject).ok().is_not_empty();
1565+
///
1566+
/// let subject: Result<u64, String> = Err("te anim adipisici mollit".to_string());
1567+
/// assert_that!(&subject).err().is_equal_to("te anim adipisici mollit");
1568+
/// ```
1569+
pub trait AssertBorrowedResultValue<'a, T, E, R> {
1570+
/// Maps the subject to the result's ok value.
1571+
///
1572+
/// If the result is an error, this method panics.
1573+
///
1574+
/// # Examples
1575+
///
1576+
/// ```
1577+
/// use asserting::prelude::*;
1578+
///
1579+
/// let subject: Result<Vec<usize>, String> = Ok(vec![1, 2, 3]);
1580+
/// assert_that!(&subject).ok().contains_exactly(&[1, 2, 3]);
1581+
/// ```
1582+
#[track_caller]
1583+
fn ok(self) -> Spec<'a, &'a T, R>;
1584+
1585+
/// Maps the subject to the result's err value.
1586+
///
1587+
/// If the result is an ok value, this method panics.
1588+
///
1589+
/// # Examples
1590+
///
1591+
/// ```
1592+
/// use asserting::prelude::*;
1593+
///
1594+
/// let subject: Result<u64, String> = Err("te anim adipisici mollit".to_string());
1595+
/// assert_that!(&subject).err().is_equal_to("te anim adipisici mollit");
1596+
/// ```
1597+
#[track_caller]
1598+
fn err(self) -> Spec<'a, &'a E, R>;
1599+
}
1600+
15561601
/// Assert that a subject of some container type holds a value that is equal to
15571602
/// the expected one.
15581603
///

src/result/mod.rs

Lines changed: 183 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
//! Implementation of assertions for `Result` values.
22
33
use crate::assertions::{
4-
AssertHasError, AssertHasErrorMessage, AssertHasValue, AssertResult, AssertResultValue,
4+
AssertBorrowedResultValue, AssertHasError, AssertHasErrorMessage, AssertHasValue, AssertResult,
5+
AssertResultValue,
56
};
67
use crate::colored::{mark_missing, mark_unexpected};
78
use crate::expectations::{HasError, HasValue, IsEqualTo, IsErr, IsOk};
@@ -27,6 +28,21 @@ where
2728
}
2829
}
2930

31+
impl<T, E, R> AssertResult for Spec<'_, &Result<T, E>, R>
32+
where
33+
T: Debug,
34+
E: Debug,
35+
R: FailingStrategy,
36+
{
37+
fn is_ok(self) -> Self {
38+
self.expecting(IsOk)
39+
}
40+
41+
fn is_err(self) -> Self {
42+
self.expecting(IsErr)
43+
}
44+
}
45+
3046
impl<'a, T, E, R> AssertResultValue<'a, T, E, R> for Spec<'a, Result<T, E>, R>
3147
where
3248
T: Debug,
@@ -51,6 +67,30 @@ where
5167
}
5268
}
5369

70+
impl<'a, T, E, R> AssertBorrowedResultValue<'a, T, E, R> for Spec<'a, &'a Result<T, E>, R>
71+
where
72+
T: Debug,
73+
E: Debug,
74+
{
75+
fn ok(self) -> Spec<'a, &'a T, R> {
76+
self.mapping(|subject| match subject {
77+
Ok(value) => value,
78+
Err(error) => {
79+
panic!("assertion failed: expected the subject to be `Ok(_)`, but was `Err({error:?})`")
80+
},
81+
})
82+
}
83+
84+
fn err(self) -> Spec<'a, &'a E, R> {
85+
self.mapping(|subject| match subject {
86+
Ok(value) => {
87+
panic!("assertion failed: expected the subject to be `Err(_)`, but was `Ok({value:?})`")
88+
},
89+
Err(error) => error,
90+
})
91+
}
92+
}
93+
5494
impl<T, E, X, R> AssertHasValue<X> for Spec<'_, Result<T, E>, R>
5595
where
5696
T: PartialEq<X> + Debug,
@@ -63,6 +103,18 @@ where
63103
}
64104
}
65105

106+
impl<T, E, X, R> AssertHasValue<X> for Spec<'_, &Result<T, E>, R>
107+
where
108+
T: PartialEq<X> + Debug,
109+
E: Debug,
110+
X: Debug,
111+
R: FailingStrategy,
112+
{
113+
fn has_value(self, expected: X) -> Self {
114+
self.expecting(HasValue { expected })
115+
}
116+
}
117+
66118
impl<T, E, X, R> AssertHasError<X> for Spec<'_, Result<T, E>, R>
67119
where
68120
T: Debug,
@@ -75,6 +127,18 @@ where
75127
}
76128
}
77129

130+
impl<T, E, X, R> AssertHasError<X> for Spec<'_, &Result<T, E>, R>
131+
where
132+
T: Debug,
133+
E: PartialEq<X> + Debug,
134+
X: Debug,
135+
R: FailingStrategy,
136+
{
137+
fn has_error(self, expected: X) -> Self {
138+
self.expecting(HasError { expected })
139+
}
140+
}
141+
78142
impl<'a, T, E, X, R> AssertHasErrorMessage<'a, X, R> for Spec<'a, Result<T, E>, R>
79143
where
80144
T: Debug,
@@ -95,6 +159,26 @@ where
95159
}
96160
}
97161

162+
impl<'a, T, E, X, R> AssertHasErrorMessage<'a, X, R> for Spec<'a, &Result<T, E>, R>
163+
where
164+
T: Debug,
165+
E: Display,
166+
X: Debug,
167+
String: PartialEq<X>,
168+
R: FailingStrategy,
169+
{
170+
fn has_error_message(self, expected: X) -> Spec<'a, String, R> {
171+
self.mapping(|result| match result {
172+
Ok(value) => panic!(
173+
r"assertion failed: expected the subject to be `Err(_)` with message {expected:?}, but was `Ok({value:?})`"
174+
),
175+
Err(error) => {
176+
error.to_string()
177+
},
178+
}).expecting(IsEqualTo {expected})
179+
}
180+
}
181+
98182
impl<T, E> Expectation<Result<T, E>> for IsOk
99183
where
100184
T: Debug,
@@ -143,6 +227,54 @@ where
143227
}
144228
}
145229

230+
impl<T, E> Expectation<&Result<T, E>> for IsOk
231+
where
232+
T: Debug,
233+
E: Debug,
234+
{
235+
fn test(&mut self, subject: &&Result<T, E>) -> bool {
236+
subject.is_ok()
237+
}
238+
239+
fn message(
240+
&self,
241+
expression: &Expression<'_>,
242+
actual: &&Result<T, E>,
243+
format: &DiffFormat,
244+
) -> String {
245+
let expected = Ok::<_, Unknown>(Unknown);
246+
let marked_actual = mark_unexpected(actual, format);
247+
let marked_expected = mark_missing(&expected, format);
248+
format!(
249+
"expected {expression} is {expected:?}\n but was: {marked_actual}\n expected: {marked_expected}"
250+
)
251+
}
252+
}
253+
254+
impl<T, E> Expectation<&Result<T, E>> for IsErr
255+
where
256+
T: Debug,
257+
E: Debug,
258+
{
259+
fn test(&mut self, subject: &&Result<T, E>) -> bool {
260+
subject.is_err()
261+
}
262+
263+
fn message(
264+
&self,
265+
expression: &Expression<'_>,
266+
actual: &&Result<T, E>,
267+
format: &DiffFormat,
268+
) -> String {
269+
let expected = Err::<Unknown, Unknown>(Unknown);
270+
let marked_actual = mark_unexpected(actual, format);
271+
let marked_expected = mark_missing(&expected, format);
272+
format!(
273+
"expected {expression} is {expected:?}\n but was: {marked_actual}\n expected: {marked_expected}"
274+
)
275+
}
276+
}
277+
146278
impl<T, E, X> Expectation<Result<T, E>> for HasValue<X>
147279
where
148280
T: PartialEq<X> + Debug,
@@ -168,6 +300,31 @@ where
168300
}
169301
}
170302

303+
impl<T, E, X> Expectation<&Result<T, E>> for HasValue<X>
304+
where
305+
T: PartialEq<X> + Debug,
306+
E: Debug,
307+
X: Debug,
308+
{
309+
fn test(&mut self, subject: &&Result<T, E>) -> bool {
310+
subject.as_ref().is_ok_and(|value| value == &self.expected)
311+
}
312+
313+
fn message(
314+
&self,
315+
expression: &Expression<'_>,
316+
actual: &&Result<T, E>,
317+
format: &DiffFormat,
318+
) -> String {
319+
let expected = &self.expected;
320+
let marked_actual = mark_unexpected(actual, format);
321+
let marked_expected = mark_missing(&Ok::<_, E>(expected), format);
322+
format!(
323+
"expected {expression} is ok containing {expected:?}\n but was: {marked_actual}\n expected: {marked_expected}"
324+
)
325+
}
326+
}
327+
171328
impl<T, E, X> Expectation<Result<T, E>> for HasError<X>
172329
where
173330
T: Debug,
@@ -193,5 +350,30 @@ where
193350
}
194351
}
195352

353+
impl<T, E, X> Expectation<&Result<T, E>> for HasError<X>
354+
where
355+
T: Debug,
356+
E: PartialEq<X> + Debug,
357+
X: Debug,
358+
{
359+
fn test(&mut self, subject: &&Result<T, E>) -> bool {
360+
subject.as_ref().is_err_and(|err| err == &self.expected)
361+
}
362+
363+
fn message(
364+
&self,
365+
expression: &Expression<'_>,
366+
actual: &&Result<T, E>,
367+
format: &DiffFormat,
368+
) -> String {
369+
let expected = &self.expected;
370+
let marked_actual = mark_unexpected(actual, format);
371+
let marked_expected = mark_missing(&Err::<T, _>(expected), format);
372+
format!(
373+
"expected {expression} is error containing {expected:?}\n but was: {marked_actual}\n expected: {marked_expected}"
374+
)
375+
}
376+
}
377+
196378
#[cfg(test)]
197379
mod tests;

0 commit comments

Comments
 (0)