this post was submitted on 04 Aug 2023
2 points (100.0% liked)
Rust
6137 readers
40 users here now
Welcome to the Rust community! This is a place to discuss about the Rust programming language.
Wormhole
Credits
- The icon is a modified version of the official rust logo (changing the colors to a gradient and black background)
founded 2 years ago
MODERATORS
you are viewing a single comment's thread
view the rest of the comments
view the rest of the comments
Just FYI -- your test isn't going to run, you need to mark it with
#[test]
.So if you're used to a language like JS or python, or even Java, you're going to be a bit frustrated at how to mock things in rust. In those languages everything is boxed. In JS or python, because they're dynamically typed, you don't have to do anything special to mock, and in Java you can either play nice and use
interface
es everywhere, or else you can do some runtime magic to mock an object of a regular class.You can do something similar in rust -- e.g. you can have a
trait Cat
and astruct RealCat
and a (or possibly many)struct FakeCat
. (There are crates that will help you with this). Then you need to either accept aBox
or a&dyn Cat
, or make your code under test generic (which can infect the rest of your code if you aren't careful), something likefn uses_a_cat(cat: C) {}
So there's not quite as easy of an answer. You also have several more options, for example you can
and get a fake (or mock, or spy, whatever test double you'd like) in all test code in your same crate. This doesn't work well across crate boundaries though, and it only lets you provide one double, so it makes sense for that double to be very generic (there are crates to do this for you as well).
So there's not really a one-size-fits-all approach. You have to think about the tradeoffs.
However I think the best overall test strategy (and it doesn't always apply, but it should be preferred when it does), is the same one used for functional programming: just accept and return values. Pure functions don't need mocks, and even impure functions can easily be tested if they don't have other side effects that you need to prevent during tests. Obviously you still need to deal with side effects if your program is going to work, but if you have lots of pure unit tests that don't need any fancy test doubles you can do end-to-end testing for all of your I/O and other messy side effects. Which as I said, doesn't always apply (sometimes you really need test doubles), but it's good to use whenever possible.