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

问题描述 投票:0回答:2

我有一个返回

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。

unit-testing rust typeerror
2个回答
9
投票

使用

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 { .. }))) }
    

0
投票
如果你不关心具体错误本身,还可以使用

is_ok

 类型的 
is_err
Result
 函数来测试变体的类型。

一个例子是:

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

return_result

 函数是在父模块中定义的。因此,可以通过 
super
 访问它。

© www.soinside.com 2019 - 2024. All rights reserved.