0 day streak
rust / expert
Snippet

Parameterizing Unit Tests via Generic Assertion Traits

By implementing a custom extension trait for Result, we can define generic, reusable, and type-parameterized assertions within our unit tests, decoupling the test harness from manual match assertions.

snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
trait AssertResultExt<T, E> {
fn assert_ok_matches<F>(self, matcher: F) where F: FnOnce(T);
}
impl<T, E> AssertResultExt<T, E> for Result<T, E>
where
E: std::fmt::Debug,
{
fn assert_ok_matches<F>(self, matcher: F)
where
F: FnOnce(T),
{
match self {
Ok(value) => matcher(value),
Err(err) => panic!("Expected Ok, but got Err: {:?}", err),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn get_even_number(x: i32) -> Result<i32, String> {
if x % 2 == 0 {
Ok(x)
} else {
Err("Not even".to_string())
}
}
#[test]
fn test_even_logic() {
let result = get_even_number(42);
result.assert_ok_matches(|val| {
assert!(val > 40);
assert_eq!(val, 42);
});
}
}
Breakdown
1
trait AssertResultExt<T, E>
Declares a trait to extend standard Result types with specialized testing assertion capabilities.
2
fn assert_ok_matches<F>(self, matcher: F)
Receives a closure that executes custom assertions on the successfully unwrapped inner value.
3
panic!("Expected Ok, but got Err: {:?}", err)
Standard panicking behavior when the result is unexpected, keeping test logs clean.
4
result.assert_ok_matches(|val| { ... })
Evaluates the assertions inside the callback, validating the logic of the tested function.