Mocks make tests worse when they replace the thing you should be testing, or when they tie the test to the implementation.
Signs of over-mocking:
- You set up five mocks to test two lines of code.
- Most assertions are
toHaveBeenCalledWithon internal collaborators. - A refactor keeps the behaviour identical, but dozens of tests break.
- A mocked repository returns data that the real query could never produce.
- You mock modules of your own code just to reach a branch.
The cost is double. Tests fail when nothing is broken. And tests pass when something is broken: a mocked repository can't catch a wrong WHERE clause or a constraint violation.
What to do instead:
- Mock only at architectural boundaries: the network, the message broker, the clock and randomness.
- Prefer fakes, or a real database running in a container.
- Assert on outcomes.
If a class needs many mocks, it often has too many responsibilities.
- Tests tied to the implementation break on harmless refactors.
- Mocks can return impossible data and hide real integration bugs.
- Mock at process boundaries, not your own internal code.
- Many mocks are a sign that a class has too many responsibilities.
Read more