While testing we tend to replace some of the unit’s collaborators with mocks as it is accustomed to call them. The problem with that name is that it is not accurate. The real name of those mocks is
test doubles and there are four of them with mock being one of the types.
One reason for this misnaming is the wide usage of mocking frameworks that do not separate the types between them (I am looking at you mockito).
So, lets try to define the four types and see when it is best to use them. We will be using a made up browser and its history and will not use any framework. Just theory:
dummy is the test double that we use whenever we know that the collaborator will not be used:
For example in the tests above we just need to check the browser’s active URL. We know that this does not evolve the browser’s history so we pass a collaborator that does nothing on every method call.
stub is the test double that we use whenever the collaborator is being used to query values:
For example in the test above we feed the browser with a pre-populated history since we know that the browser will need to peek for the last visited URL.
mock is the test double that we use whenever the collaborator is being used to perform an action:
For example in the test above we need to make sure that the browser saves the provided URL to its history so we use a collaborator that can verify this behavior.
fake is the test double that we use whenever we need the collaborator to provide us a usable business logic:
For example in the test above we need a history instance that works as expected (a simple stack) but without the hassle of having a database or using the file system.
Having your own test doubles per case makes the code simpler and more readable but does that mean that we should remove our mocking frameworks? In my opinion no. Having a framework saves you a lot of time and keeps things consistent, especially in big projects with lots of developers.
Knowing the theory behind something is always good since it lays a common foundation for discussions and decisions. A mix of the two, framework and theory, could be achieved and help the test code in readability.
For example, we can keep using Mockito’s mock but name the variable
stubBlahBlah if is used as a stub. This way the reader will know what to expect.
PS #1: Spock testing framework, besides being a great tool, provides a way to separate stubs from mocks not just in semantics but in usage too (ex: you cannot verify something when using a stub)
PS #2: There is another type of test double called
Spy which is a toned down mock that helps in keeping state when a certain behavior takes place but does not verify it.