繁体   English   中英

如何测试 Box 中错误的类型<dyn Error> ?

[英]How to test the type of an error in Box<dyn Error>?

我有一个返回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();
}

如果您关心特定错误,我建议您避免使用 trait 对象。 特征对象的要点是您不需要知道具体类型是什么。

相反,您可以使用帮助您构建错误类型的库,例如我的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 { .. })))
}

如果您不关心特定错误本身,您还可以使用Result类型的is_okis_err函数来测试变体的类型。

一个例子是:

#[cfg(test)]
mod tests {
    #[test]
    fn should_return_error() {
        assert!(super::return_result().is_err());
    }
}

注意:假设return_result函数是在父模块中定义的。 因此,可以使用super访问它。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM