Issues in asserting Result

I got the following error message

binary operation `==` cannot be applied to type `std::result::Result<card::Rank, anyhow::Error>`rustc[E0369](https://doc.rust-lang.org/error-index.html#E0369)

when asserting a Result object.

assert_eq!(Rank::from_char('2'), Ok(Rank::_2));

Any idea what went wrong? What is the idiomatic way to assert a Result?

I'd suggest using assert!(matches!(Rank::from_char('2'), Ok(Rank::_2)) instead.

The issue here is that

  • a type supports comparing with == (which is what assert_eq! calls under the hood) only if it implements the PartialEq trait
  • Result<T, E> is PartialEq only if both T and E are PartialEq
  • anyhow::Error is not PartialEq

Hence you cannot use assert_eq! to compare two values of type Result<Rank, anyhow::Error> (and there's not really anything you can do about this, because you don't control anyhow::Error).

In the future you may be able to use the Result::contains method for this, but that's not stable yet.

1 Like

Can I use assert! and matches! to assert specific error types too? If so, mind to give an example?

I want to to assert whether an expression return an error. The following code works.

assert!(matches!(Rank::from_char('Z'), Err(_))

However, I want to check more specifically whether it is Err(ParseCardError::InvalidSymbolForRank('Z')).

anyhow::Error is opaque (it doesn't expose its fields), so you can't pattern-match against it effectively, which is what matches! does. But if you have a more "transparent" error type, like

enum RankError {
    NotARank(char),
    Custom(&'static str),
}

then you can certainly scrutinize it that way:

assert!(matches!(Rank::from_char('z'), Err(RankError::NotARank('z'))));

Ah, unfortunately, I used anyhow::Error as the Error type and ParseCardError::InvalidSymbolForRank is converted to anyhow::Error in the code. Sounds like I couldn't do much here.

Another approach is to use unwrap() when asserting success and unwrap_err() when asserting failure. For example:

assert_eq!(Rank::from_char('2').unwrap(), Rank::_2);

You can use anyhow::Error::downcast to check the error against a specific type:

let err = Rank::from_char('z').unwrap_err().downcast().unwrap();
assert_eq!(err, RankError::NotARank('z')));
2 Likes

This topic was automatically closed 90 days after the last reply. We invite you to open a new topic if you have further questions or comments.