Reputation: 16422
I have the following struct
:
pub struct Settings {
pub something: String
}
with the following constructor:
impl Settings {
fn new(path: &Path) -> Settings {
if !path.exists() {
fail!("Configuration file not found.");
}
return Settings{something:String::new()};
}
}
I've created a unit test to see what happens when I create a struct with Path
s that point to existing and none existing files:
mod tests {
#[test]
fn test_new_valid_path() {
use configuration::Settings;
let path = &Path::new("emperor.ini");
let settings = Settings::new(path);
assert!(settings);
}
#[test]
fn test_new_invalid_path() {
use configuration::Settings;
let path = &Path::new("emperor.xml");
let settings = Settings::new(path);
}
}
But when I run my tests thus: rustc --test meh.rs; ./meh --nocapture
I get the following output:
<std macros>:3:12: 40:20 error: cannot apply unary operator `!` to type `configuration::Settings`
<std macros>:3 if !$cond {
<std macros>:4 fail!("assertion failed: {:s}", stringify!($cond))
<std macros>:5 }
<std macros>:6 );
<std macros>:7 ($cond:expr, $($arg:expr),+) => (
<std macros>:8 if !$cond {
...
<std macros>:1:1: 12:2 note: in expansion of assert!
shogun.rs:40:4: 40:22 note: expansion site
error: aborting due to previous error
How can I test struct instantiation?
Upvotes: 4
Views: 5438
Reputation: 90752
I think you are misunderstanding the model of how these things work.
A function that has a return type of Settings
—well, its value when it returns is a Settings
object which is guaranteed to be correctly instantiated. If we removed your assert!(settings);
line, the code would do exactly what you’re wanting. (assert!
expects a boolean as its first argument, by the way, just as if
requires a boolean expression to follow it.)
If the path is one that does not exist, then the fail!
will come into play and the task will fail, unwinding; the Settings::new
call never returns. Triggering task failure is exactly what assert!(…)
does, also.
To put it all another way: the very fact that that line is executed proves that it is initialised correctly.
Incidentally, failing like that is typically considered bad form; better would be to return an Option<Settings>
, and not to use the name new
but rather something that indicates that you’ll be loading it from a file; something like this:
impl Settings {
fn load(path: &Path) -> Option<Settings> {
if !path.exists() {
None
} else {
Some(Settings { something: String::new() })
}
}
}
Upvotes: 7
Reputation: 79
I think the problem is this line
assert!(settings);
assert just throws an error if the boolean argument inside is false but settings in this case is not a boolean, it's of type configuration::Settings
cannot apply unary operator `!` to type `configuration::Settings`
To test if you've got valid settings back do something like
assert!(settings.something.is_empty())
Upvotes: 0