我有一个返回
Result<(), Box<dyn Error>>
的函数。我正在为此函数编写一个测试用例,其中该函数应返回变体 VerifyError::LinearCombinationError
(playground): 的错误
use std::error::Error;
use std::fmt::{Debug, Display, Formatter};
#[derive(Debug, PartialEq, Eq)]
enum VerifyError {
LinearCombination,
}
impl Error for VerifyError {}
impl Display for VerifyError {
fn fmt(&self, f: &mut Formatter) -> std::fmt::Result {
write!(f, "{:?}", self)
}
}
fn return_result() -> Result<(), Box<dyn Error>> {
Err(Box::new(VerifyError::LinearCombination))
}
pub fn main() {
let res = return_result();
println!("debug print is: {:?}", res);
// Program does not compile when below line is not commented out
// assert_eq!(Some(VerifyError::LinearCombination), res.err());
}
取消注释该行会给出错误消息:
error[E0308]: mismatched types
--> src/main.rs:26:5
|
26 | assert_eq!(Some(VerifyError::LinearCombination), res.err());
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected enum `VerifyError`, found struct `Box`
|
= note: expected enum `Option<VerifyError>`
found enum `Option<Box<dyn std::error::Error>>`
= note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
我正在使用 Rust 1.53.0。
Error::is
测试错误特征对象是否具有特定的具体类型,或使用 Error::downcast
将其转换为该具体类型:
use std::error::Error;
fn example() -> Result<(), Box<dyn Error>> {
Err(std::io::Error::last_os_error().into())
}
#[test]
fn is_from_io_error() {
let e = example().err().unwrap();
assert!(e.is::<std::io::Error>());
let _e = e.downcast::<std::io::Error>().unwrap();
}
如果您关心特定错误,我建议您避免使用特征对象。特征对象的要点是您不需要知道具体类型是什么。
相反,您可以使用帮助您构建错误类型的库,例如我的SNAFU。此用法显示了枚举中的包装错误,可以通过模式匹配来测试特定类型:
use snafu::{Snafu, ResultExt}; // snafu = "0.7.0-beta.0"
#[derive(Debug, Snafu)]
enum Error {
Example { source: std::io::Error }
}
fn example() -> Result<(), Error> {
Err(std::io::Error::last_os_error()).context(ExampleSnafu)
}
#[test]
fn is_from_io_error() {
let e = example();
assert!(matches!(e, Err(Error::Example { .. })))
}
is_ok
类型的
is_err
和
Result
函数来测试变体的类型。一个例子是:
#[cfg(test)]
mod tests {
#[test]
fn should_return_error() {
assert!(super::return_result().is_err());
}
}
注意:假设 return_result
函数是在父模块中定义的。因此,可以通过
super
访问它。