Как я могу утверждать, что перечисление является конкретным вариантом, если меня не волнуют его поля? - PullRequest
0 голосов
/ 01 июля 2018

Я хотел бы проверить перечисления с полями в тестах, игнорируя при этом фактическое значение полей.

Рассмотрим следующий пример:

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

площадка

Я бы хотел использовать assert_eq! здесь, но компилятор говорит мне:

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

Это похоже на Почему я получаю ошибку, когда шаблон сопоставляет структурный вариант перечисления с полями? , но решение не применимо в моем случае.

Конечно, я могу использовать match и сделать это сам, но возможность использовать assert_eq! будет меньше работы.

Ответы [ 2 ]

0 голосов
/ 01 июля 2018

Ваш исходный код можно настроить для работы с новым макросом:

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,
        }
    }
}

Я надеюсь, что когда-нибудь варианты enum можно будет преобразовать в их собственный тип, чтобы избежать этой дополнительной структуры.

0 голосов
/ 01 июля 2018

Простым решением здесь было бы сделать противоположное утверждение:

assert!(return_with_fields() != MyEnum::WithoutFields);

или даже проще:

assert_ne!(return_with_fields(), MyEnum::WithoutFields);

Конечно, если в вашем перечислении больше участников, вам придется добавить больше утверждений, чтобы охватить все возможные случаи.

В качестве альтернативы, и это, вероятно, имел в виду OP, так как assert! просто паникует в случае сбоя, тест может использовать сопоставление с образцом и напрямую вызывать panic!, если что-то не так:

match return_with_fields() {
    MyEnum::WithFields {..} => {},
    MyEnum::WithoutFields => panic!("expected WithFields, got WithoutFields"),
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...