Reputation: 6352
Let's say I have the following Rust enum:
enum Food {
Fruit(String), // the String represents the food's name
Vegitable(String),
}
How can I test that a function actually generates an apple and not a banana?
For instance, I want a test something like the following:
#[test]
fn is_correct_food() {
let apple = Food::Fruit("Banana".to_string()); // comes from tested function
assert!(matches!(apple, Food::Fruit("Apple".to_string())));
}
When I run the above code, I get the following error:
error: expected one of `)`, `,`, `...`, `..=`, `..`, or `|`, found `.`
--> src/lib.rs:8:48
|
8 | assert!(matches!(apple, Food::Fruit("Apple".to_string())));
| ^
| |
| expected one of `)`, `,`, `...`, `..=`, `..`, or `|`
| help: missing `,`
After doing some research, I learned this error occurs because you cannot call functions inside pattern matching statements. If I try and instead abstract the name into a variable (to remove the function call), the test passes because the pattern matches.
#[test]
fn is_correct_food() {
let apple = Food::Fruit("Banana".to_string()); // comes from tested function
let name = "Apple".to_string();
assert!(matches!(apple, Food::Fruit(name)));
}
It is possible to use a match
statement to get the variable out from the contents. However, logic should be avoided in tests at all costs. Additionally, the actual object I need to test is a lot more complicated, which would require many nested match
statements. So I'd like to avoid anything that looks like the following test:
#[test]
fn is_correct_food() {
let apple = Food::Fruit("Banana".to_string()); // comes from tested function
match apple {
Food::Fruit(name) => assert_eq!(name, "apple"),
_ => panic!("should be a fruit"),
}
}
How to match a String against string literals?
Does pattern matching with a top-level string. I want pattern matching inside a nested object.
Upvotes: 1
Views: 140
Reputation: 59817
Much like you can add an if
after the pattern in a match block, called a match guard, you can do the same with matches!
:
matches!(apple, Food::Fruit(fruit) if fruit == "Apple")
The documentation for matches!
mentions this functionality and includes an example that demonstrates it.
Upvotes: 2