Reputation: 5121
So I have this custom error,
use std::fmt;
#[derive(Debug)]
pub enum XError {
TagNotFound,
}
impl std::error::Error for XError {}
impl fmt::Display for XError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
XError::TagNotFound => write!(f, "couldn't find tag"),
}
}
}
And then I have a function pub fn validate() -> Result<String, Box<dyn std::error::Error>>
.
Now in my test, how do I check if error returned by validate
is XError::TagNotFound
?
I tried doing,
let b = validate(param)
.unwrap_err()
.downcast_ref::<XError::TagNotFound>();
But I get this expected type, found variant "XError::TagNotFound" not a type
.
Upvotes: 3
Views: 2606
Reputation: 601809
The problem with your code is that XError::TagNotFound
is not a type, as the error message says. It's a variant of the XError
enum.
You have a Box<dyn Error>
, and you want to check whether that error is XError::TagNotFound
. This check consists of two steps:
Box<dyn Error>
to XError
, if possible.XError
is XError::TagNotFound
.Step 1 can be performed using my_error.downcast_ref::<XError>()
, which will return an Option<&XError>
. Step 2 is normal pattern matching, and can be performed with if let
, match
or the matches!()
macro, whatever you prefer. Here is one option:
if let Some(&XError::TagNotFound) = my_error.downcast_ref::<XError>() {
// handle error
}
In a unit test, using the matches!()
macro is probably more appropriate:
assert!(matches!(my_error.downcast_ref::<XError>(), Some(&XError::TagNotFound));
Upvotes: 9