HiveBrain v1.2.0
Get Started
← Back to all entries
snippetrustMajor

How do I assert an enum is a specific variant if I don't care about its fields?

Submitted by: @import:stackoverflow-api··
0
Viewed 0 times
enumabouthowvariantdonassertitsspecificfieldscare

Problem

I'd like to check enums with fields in tests while ignoring the actual value of the fields for now.

Consider the following example:

enum MyEnum {
    WithoutFields,
    WithFields { field: String },
}

fn return_with_fields() -> MyEnum {
    MyEnum::WithFields {
        field: "some string".into(),
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn example() {
        assert_eq!(return_with_fields(), MyEnum::WithFields {..});
    }
}


playground

I'd like to use assert_eq! here, but the compiler tells me:

error: expected expression, found }
--> src/lib.rs:18:64
|
18 | assert_eq!(return_with_fields(), MyEnum::WithFields {..});
| ^ expected expression


This is similar to Why do I get an error when pattern matching a struct-like enum variant with fields?, but the solution does not apply in my case.

Of course, I can use match and do it myself, but being able to use assert_eq! would be less work.

Solution

Rust 1.42

You can use std::matches:

assert!(matches!(return_with_fields(), MyEnum::WithFields { .. }));


Previous versions

Your original code can be made to work with a new macro:

macro_rules! is_enum_variant {
    ($v:expr, $p:pat) => (
        if let $p = $v { true } else { false }
    );
}

#[test]
fn example() {
    assert!(is_enum_variant!(return_with_fields(), MyEnum::WithoutFields {..}));
}


Personally, I tend to add methods to my enums:

fn is_with_fields(&self) -> bool {
    match self {
        MyEnum::WithFields { .. } => true,
        _ => false,
    }
}


I also tend to avoid struct-like enums and instead put in extra work:

enum MyEnum {
    WithoutFields,
    WithFields(WithFields),
}

struct WithFields { field: String }

impl MyEnum {
    fn is_with_fields(&self) -> bool {
        match self {
            MyEnum::WithFields(_) => true,
            _ => false,
        }
    }

    fn as_with_fields(&self) -> Option {
        match self {
            MyEnum::WithFields(x) => Some(x),
            _ => None,
        }
    }
    
    fn into_with_fields(self) -> Option {
        match self {
            MyEnum::WithFields(x) => Some(x),
            _ => None,
        }
    }
}


I hope that some day, enum variants can be made into their own type to avoid this extra struct.

Code Snippets

assert!(matches!(return_with_fields(), MyEnum::WithFields { .. }));
macro_rules! is_enum_variant {
    ($v:expr, $p:pat) => (
        if let $p = $v { true } else { false }
    );
}

#[test]
fn example() {
    assert!(is_enum_variant!(return_with_fields(), MyEnum::WithoutFields {..}));
}
fn is_with_fields(&self) -> bool {
    match self {
        MyEnum::WithFields { .. } => true,
        _ => false,
    }
}
enum MyEnum {
    WithoutFields,
    WithFields(WithFields),
}

struct WithFields { field: String }

impl MyEnum {
    fn is_with_fields(&self) -> bool {
        match self {
            MyEnum::WithFields(_) => true,
            _ => false,
        }
    }

    fn as_with_fields(&self) -> Option<&WithFields> {
        match self {
            MyEnum::WithFields(x) => Some(x),
            _ => None,
        }
    }
    
    fn into_with_fields(self) -> Option<WithFields> {
        match self {
            MyEnum::WithFields(x) => Some(x),
            _ => None,
        }
    }
}

Context

Stack Overflow Q#51121446, score: 92

Revisions (0)

No revisions yet.