Coming from an enterprise-grade language like Kotlin, Java, or C# to Rust requires a bit of learning 📈. There are so many things that I absolutely love about Rust, compared to other languages. Rust, for instance, brings its own testing framework out of the box!
However, if you’ve used well-established testing libraries like JUnit, MockK, Mockito, and alike, you will quickly find that writing tests in Rust is not as straightforward, as you might think.
Thankfully, there are some ways to make testing Rust programs a lot easier. This guide is here to help you with your first steps in writing testable Rust code. I will compare testing in Rust to Kotlin, and hopefully, you’ll be able to grasp the essentials, even if you come from another language.
Where do Unit Tests live in Rust?
In contrast to Kotlin or Java, where you put all your tests under /src/test, Rust tests live in your implementation file. Let’s say you create a service.rs file to perform access to a user database, you’d put your tests at the very bottom of the service.rs file in the mod tests module. It is common practice to do it this way within the Rust ecosystem. We will see it later in this article. Also, putting your tests this close to your code has many advantages:
- directly find whether a module has tests or not 🤠
- encapsulate logic, if you have the discipline 🙄
- forces you to have smaller modules (nobody likes files with > 1K LOC!) 😱
Integration tests, on the other hand, may live in a dedicated integration_tests folder. But those are not part of this guide (partially, because, in integration tests, you don’t mock! 🤯).
A note about test structures and strategies
In this article, I’ll describe how to test very granular parts of your code, e.g. a function, a module, and so on. This is purely to describe how to do it.
In general, you should always aim to test behaviors, not functions, classes, or modules. This helps keep the implementation details out of your test and reduces dependencies.