Reputation: 10764
I write tests in other languages where I explicitly define expected and actual values. In Rust, I was running into lifetime errors because my test code creates a struct that uses a value from another struct.
Two ways I have found to avoid this is to:
I have seen many posts asking how to avoid excessive cloning so I wonder if there is a more idiomatic way of doing this.
Can I get rid of the clone
in the following test:
#[derive(Clone, Debug, PartialEq)]
struct SomethingElse {
a: u16,
}
struct Something {
inner: SomethingElse,
}
impl Something {
pub fn do_something(&self) -> SomethingElse {
return self.inner.clone();
}
}
mod tests {
#[cfg(test)]
use super::*;
#[test]
fn something_does_something() {
let expected = SomethingElse { a: 1 };
let something = Something {
inner: expected.clone(),
};
assert_eq!(something.do_something(), expected);
}
}
Upvotes: 1
Views: 988
Reputation: 43743
I'm not saying that this is idiomatic, or wise in this particular case, but you can avoid cloning by comparing through a reference. Instead of
let expected = SomethingElse { a: 1 };
let something = Something {
inner: expected.clone(),
};
assert_eq!(something.do_something(), expected);
write
let something = Something {
inner: SomethingElse { a: 1 },
};
let expected = &something.inner;
assert_eq!(&something.do_something(), expected);
I would only do this if it is actually important to the properties being tested that the value not be cloned (perhaps because its impl Clone
does something special).
Upvotes: 2
Reputation: 58695
In any programming language, "best practices" for production code are very different from best practices for tests. In particular, you probably don't much care about performance in tests. The most important thing is that someone reading the test can see what it does and that it doesn't contain too much noise or indirection that distracts from what the test is actually testing.
If you need to assert that a field of one struct contains the same data as some field of another struct, cloning seems like exactly the right thing to do. In your case, since it's simple, you might even consider duplicating the code that describes the inner struct:
#[test]
fn something_does_something() {
let something = Something {
inner: SomethingElse { a: 1 },
};
assert_eq!(something.do_something(), SomethingElse { a: 1 });
}
Upvotes: 3