When I was just getting into unit testing the subject question was rather hard to me: it’s not actually obvious for a novice. The answer to it came from a unit testing book I think is very nice and useful - “The Art of Unit Testing” by Roy Osherove.
Mock or stub?
So what’s the core difference between mock and stub? The answer is: mocks can fail tests and stubs can not. You may think this minor point is not important but it is. Basically when you test something you have the following two components: code under test (CUT) and test itself. There are two different cases for testing:
1. You may run CUT and validate it results – it’s actually testing CUT internals
2. You may run CUT and validate how it communicated with some external service – it’s actually testing CUT externals
The first case usually accompanied by stubs – some stub objects that you use to pass initialization information to CUT. They just provide data and do nothing more.
The second case is usually accompanied by stubs and a mock. Let’s say you have some IExternalService your CUT communicates with. After running CUT you want to be sure that two IExternalService methods were called with some valid parameters. You can write some custom class that implements this interface but the simplest option is to use a mock. Mock allows you to specify what methods in what order with what parameters should be called. After CUT run you can validate mock and see whether it fits your expectations.
The rule of thumb here is to have one mock in your test at max. Why is that? The answer is simple: when you use two mocks and validate both of them in a single test it means that you test two different pieces of logic in one test. That may be a result of scattered logic (violation of Single Responsibility Principle) or just a bad test design – anyway it’s a bad practice. What though should be remembered is that you can use as many stubs in your test as you wish – they just provide initialization data and can’t fail your test.