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 Paths 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?
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() })
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With