the situation is as following. Few years ago, Gerard Meszaros did a fantastic things of putting up a coherent nomenclature in his book "xUnit Test Patterns". Some of the terms are now widely used but not always coherently, and not always with the same meaning that Meszaros defined (personally I feel that we, as a community, have lost our chance to make our communication clear by misusing and overusing many of them).
You ask about four types of so-called test-doubles, which is a generic name for all types of objects which pretend to be real collaborators of a class (of a SUT, to be more precise). The definitions are as follows (I have them described in the book, but I will come up with ad-hoc definitions here):
* dummy - not used but has to be there (it is required so the code compiles and runs but its functionality is not used during tests) - do not worry about it, you will rarely need it,
* fake - pretends to be a someone else but is less powerful (e.g. in-memory database instead of full-blown database installation, but good enough for at least some kind of tests)
* stub - provides data to tested class (to a SUT) - its task is to pass
* mock - used to verify if some methods were called on collaborating objects (verification of indirect outputs); the term "mock" is also commonly used as an umbrella name for all test-doubles (which brings confusion, but I think this battle is already lost...)
If you dig some more you will also encounter saboteur (a specialized stub which throws all kinds of exceptions thus allowing to test many specific errors-related scenarios), or a test-spy (with at least two meanings - one which is almost identical with mock, and the other being a name of a special technique of substituting only selected methods of mocked object) and probably some more.
When it comes to distinguishing between these various things, I think it is crucial to understand the difference between mock and stub. This is because they play very different role in tests, and confusing them may lead to overspecified tests. What is important is that we verify behaviour of mocks (or more precisely, we verify if tested class calls specific methods of mock) but we do not do that with stubs. We expect stubs to provide us some values, but we do not really care if they do it or not (we do not verify if tested class calls specific methods of stubs). This allows for writing very focused tests, where only specific scenario is being verified, and results in tests having minimal coupling with implementation (however, tests which use test-doubles are always glued to implementation!).
Book author: Practical Unit Testing with TestNG and Mockito
posted 8 years ago
Thank you, Tomek. It is useful to think in these terms, even if most people are going to use the blanket term 'mock' for all of them.
My guess is that, using your definitions, there are more 'fakes' and 'stubs' out there in the wild than there are 'mocks' even though most people probably call them 'mocks'. I hadn't heard the term 'saboteur' before, but I do use them frequently.