tomasbasham
tomasbasham

Reputation: 1734

Testing an enum (custom error) with data from another module

I've created a custom error type using an enum to support multiple error conditions (omitted in example) but I am not able to test the following code without providing the data (in this case a str::Utf8Error) to the enum to perform a comparison.

use std::fmt;
use std::str;

#[derive(Debug, PartialEq)]
pub enum ClaimsError {
    ParseError(str::Utf8Error),
    // Other variants omitted.
}

impl std::error::Error for ClaimsError {}

impl fmt::Display for ClaimsError {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            ClaimsError::ParseError(ref err) => err.fmt(f),
        }
    }
}

pub fn from_slice(token: &[u8]) -> Result<&str, ClaimsError> {
    str::from_utf8(&token).map_err(|e| ClaimsError::ParseError(e))
}

#[cfg(test)]
mod tests {
    use super::{from_slice, ClaimsError};

    #[test]
    fn bad_token_fails() {
        assert_eq!(
            from_slice(&[0xF8]).unwrap_err(),
            ClaimsError::ParseError // <-- Here is the problem line.
        );
    }
}

fn main() {
    match from_slice(&[0xF8]) {
        Ok(_) => println!("great"),
        Err(ClaimsError::ParseError(err)) => println!("{}", err),
    }
}

Understandably the types do not match, thus causing the issue, so in an attempt to fix it I've tried changing the assertion to:

#[test]
fn bad_token_fails() {
    assert_eq!(
        from_slice(&[0xF8]).unwrap_err(),
        ClaimsError::ParseError(str::Utf8Error{})
    );
}

However it is not possible to create a str::Utf8Error this way because it contains only private fields. For the sake of my test I don't need to match the exact error, I am only concerned whether the error value returned from from_slice is of type ClaimsError::ParseError.

I've taken a look at the Error trait and in particular the is method stood out to me but I'm not sure if this is what I want or how to use it in this case. Any help solving this is appreciated.

(link) to a rust playground with the above code.

Upvotes: 2

Views: 147

Answers (1)

Yannick Funk
Yannick Funk

Reputation: 1581

You can use pattern matching to match on the result of from_slice(&[0xF8]).unwrap_err()

#[test]
fn bad_token_fails() {
    match from_slice(&[0xF8]).unwrap_err() {
        ClaimsError::ParseError(_) => assert!(true),
        _ => assert!(false)
    }
}

This test succeeds if the result is of type ClaimsError::ParseError and fails if the result is of other types.

As @Cerberus stated, you could also use the matches! macro, to avoid using assert!(true) and assert!(false):

#[test]
fn bad_token_fails() {
    assert!(matches!(
        from_slice(&[0xF8]),
        Err(ClaimsError::ParseError(_))
    ));
}

Upvotes: 3

Related Questions