Maybe.
But first, I’ll start by clarifying that developers asking that question usually mean “test doubles“, instead of “mocks”.
Some situations that might indicate code smell in tests include:
- using several test doubles to test one thing
- complex test doubles setup
Both cases aren’t only an indication of a code smell in the test; they often indicate a bigger problem: code smell in the design!
If the system under test (SUT) requires too many test doubles to satisfy its dependencies, it likely violates the Interface Segregation Principle
A client should never be forced to implement an interface that it doesn’t use, or clients shouldn’t be forced to depend on methods they do not use.
Take the example below:
public class SomeClass(Dependency1 Dependency1, Dependency2 Dependency2, Dependency3 Dependency3, Dependency4 Dependency4) { public void SomeMethod() { if (dependency1.CheckThis() && dependency2.CheckThat() && dependency3.CheckSomethingElse() && dependency4.FinalCheck()) { // do the thing... } } }
To write a unit test for SomeMethod, we would need mock each one of the 4 dependencies.
By inspecting how those dependencies are used, we could identify a new abstraction that offers what SomeClass needs:
public class SomeClass(Dependency Dependency) { public void SomeMethod() { if (dependency.CanIDoTheThing()) { // do the thing... } } }
Now there’s only one dependency to deal with in tests, and it’s easier to learn what that dependency provides.
An example of code smell
Here’s a test I’ve run into many years ago:
According to the name of the test, it verifies that the “PUT method returns OK and PortfolioModel when service response is successful“.
When I’ve read through the test, these considerations came to mind:
- Number of stubs and mocks (mockPortfolioService, portModel, response, portfolioModel)
- Overuse of Arg.Any
- Arg.Any hiding the meaning/intent of several parameters
- Unclear what “Configure” is all about (what does it mean to return true from it?)
- What’s the difference between portModel and portfolioModel? Why are both needed?
- The file had about 40 tests that looked very similar to this one in terms of mocks and stubs; a product of copy-and-paste.
After raising the issues with the developers on the team, we identified the design issues that resulted in tests having to be written that way. The tests were rewritten to isolate and call out the issue, and a design change was proposed.