I was going through an online course on test driven development and came across the concept of test doubles. As per the definition of test double in the course :
Test Doubles : Test doubles are objects that are used in unit tests as replacement to the real production system collaborators.
I got an idea what test doubles mean. But then it was mentioned there are various types of test doubles. The ones mentioned in the course were :
Dummy : Objects that can be passed around as necessary but do not have any type of test implementation and should never be used.
Fake : These objects generally have a simplified functional implementation of a particular interface that is adequate for testing but not for production.
Stub : These objects provide implementation with canned answers that are suitable for the tests.
Spies : These objects provide implementation that record the values that were passed in so they can be used by the tests.
Mocks : These objects are pre-programmed to expect specific calls and parameters and can throw exceptions when necessary.
I have worked with mocks before and do have a brief idea of what they are and how to use them. Though I was confused regarding the other mentioned types of test doubles.
Can someone help me with difference between these types of test doubles and when to use one ?
Dummy is sort of an odd case, in that you are using a dummy because the code under test doesn't actually use the dummy; in other words, the composition of the system is requiring you to supply some superfluous elements. Often, this is a hint that the logic you are testing should be accessible via a more specific interface.
Stubs and Fakes are typically used when a test scenario requires that the code under test obtains values from some dependency.
A stub is very focused; it doesn't pretend to do the right thing internally, but instead just returns some canned answer. For instance, you might use a stub to mimic a specific failure mode.
Fake is badly named - it's a real implementation of the dependency, just one that is optimized for testing (small, deterministic, in memory) rather than optimized for production (scale). In some circles, you'll hear substitute, rather than "fake".
Spies and mocks are typically used when you are trying to determine that your code sends the right information to a dependency, without the costs of being coupled to that dependency.
Spies normally maintain a history of messages that they receive during testing, which can later be verified against an expected message list. Mocks are a more active expression of that idea, where assertions are made about the behavior of the code under test while the scenario is running, rather than afterwards.