我现在想在测试中检查带有字段的枚举,而暂时忽略字段的实际值。
考虑以下示例:
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
这类似于Why do I get an error when pattern matching a struct-like enum variant with fields?,但该解决方案不适用于我的情况。
当然,我可以自己使用match
,但是可以使用assert_eq!
的工作会更少。
答案 0 :(得分:4)
一个简单的解决方案是做相反的断言:
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"),
}
答案 1 :(得分:2)
您的原始代码可以与新的宏一起使用:
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,
}
}
我也倾向于避免使用类似struct的枚举,而是投入额外的工作:
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,
}
}
}
我希望有一天,可以将枚举变量制成自己的类型,以避免这种额外的结构。
答案 2 :(得分:0)
我会使用像@Shepmaster建议的宏,但是会报告更多错误(例如现有的assert!
和assert_eq!
宏:
macro_rules! assert_variant {
($value:expr, $pattern:pat) => ({
let value = &$value;
if let $pattern = value {} else {
panic!(r#"assertion failed (value doesn't match pattern):
value: `{:?}`,
pattern: `{}`"#, value, stringify!($pattern))
}
})
// TODO: Additional patterns for trailing args, like assert and assert_eq
}