【问题标题】:How do you test for a specific Rust error?你如何测试特定的 Rust 错误?
【发布时间】:2018-11-02 19:42:33
【问题描述】:

我可以找到检测 Rust 是否给我错误的方法,

assert!(fs::metadata(path).is_err())

source

如何测试特定错误?

【问题讨论】:

标签: unit-testing testing error-handling rust


【解决方案1】:

如果是impl Debug + PartialEq,可以直接比较返回的Err变体:

#[derive(Debug, PartialEq)]
enum MyError {
    TooBig,
    TooSmall,
}

pub fn encode(&self, decoded: &'a Bytes) -> Result<&'a Bytes, MyError> {
    if decoded.len() > self.length() as usize {
        Err(MyError::TooBig)
    } else {
        Ok(&decoded)
    }
}
assert_eq!(fixed.encode(&[1]), Err(MyError::TooBig));

【讨论】:

  • Result.err 获取Option — 为什么不直接比较呢?
  • @Shepmaster Option 不是Result 的变体。不确定我是否理解你的问题。昨天也刚开始编程 Rust,所以这里可能会遗漏一些明显的东西
  • 为什么不和Err(MyError::TooBig)比较呢?
  • 当我尝试我得到expected enum 'std::result::Result', found enum 'fixed::Error'
  • Err(MyError::TooBig)MyError::TooBig 不同
【解决方案2】:

以下解决方案不需要实现 PartialEq 特征。比如std::io::Error没有实现这个,需要更通用的解决方案。

在这些情况下,您可以从 matches crate 借用宏 assert_matches。它通过提供更简洁的模式匹配方式来工作,宏很短,你也可以输入它:

macro_rules! assert_err {
    ($expression:expr, $($pattern:tt)+) => {
        match $expression {
            $($pattern)+ => (),
            ref e => panic!("expected `{}` but got `{:?}`", stringify!($($pattern)+), e),
        }
    }
}

// Example usages:
assert_err!(your_func(), Err(Error::UrlParsingFailed(_)));
assert_err!(your_func(), Err(Error::CanonicalizationFailed(_)));
assert_err!(your_func(), Err(Error::FileOpenFailed(er)) if er.kind() == ErrorKind::NotFound);

完整的游乐场可构建示例,例如 Error 枚举:

#[derive(Debug)]
pub enum Error {
    UrlCreationFailed,
    CanonicalizationFailed(std::io::Error),
    FileOpenFailed(std::io::Error),
    UrlParsingFailed(url::ParseError),
}

pub fn your_func() -> Result<(), Error> {
    Ok(())
}

#[cfg(test)]
mod test {
    use std::io::ErrorKind;
    use super::{your_func, Error};

    macro_rules! assert_err {
        ($expression:expr, $($pattern:tt)+) => {
            match $expression {
                $($pattern)+ => (),
                ref e => panic!("expected `{}` but got `{:?}`", stringify!($($pattern)+), e),
            }
        }
    }

    #[test]
    fn test_failures() {
        // Few examples are here:
        assert_err!(your_func(), Err(Error::UrlParsingFailed(_)));
        assert_err!(your_func(), Err(Error::CanonicalizationFailed(_)));
        assert_err!(your_func(), Err(Error::FileOpenFailed(er)) if er.kind() == ErrorKind::NotFound);
    }

}

【讨论】:

    猜你喜欢
    • 2023-04-09
    • 2019-07-02
    • 2022-07-10
    • 1970-01-01
    • 2022-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多