Don’t mock your database, it’s an implementation detail
The use of mocks in unit testing is a controversial topic (maybe less so now than several years ago). I remember how, throughout my programming career, I went from mocking almost every dependency, to the “no-mocks” policy, and then to “only mock external dependencies”.
None of this practices are good enough. In this article, I’ll show you which dependencies to mock, and which to use as is in your tests.
What is a mock?
Before jumping to the topic of when to mock, let’s discuss what a mock is.
Mock vs test double
People often use the terms test double and mock as synonyms, but technically, they are not:
- A test double is an overarching term that describes all kinds of non-production-ready, fake dependencies in tests. Such a dependency looks and behaves like its release-intended counterpart but is actually a simplified version that reduces complexity and facilitates testing. This term was introduced by Gerard Meszaros in his book xUnit Test Patterns: Refactoring Test Code. The name itself comes from the notion of a stunt double in movies.
- A mock is just one kind of such dependencies.
According to Gerard Meszaros, there are 5 types of test doubles:
Such a variety may look intimidating, but in reality, they can all be grouped together into just two types: mocks and stubs.
The difference between these two types boils down to the following:
- Mocks help to emulate and examine outcoming interactions. These interactions are calls the system under test (SUT) makes to its dependencies to change their state.
- Stubs help to emulate incoming interactions. These interactions are calls the SUT makes to its dependencies to get input data.
For example, sending an email is an outcoming interaction: that interaction results in a side effect in the SMTP server. A test double emulating such an interaction is a mock.