Test Double is a generic term for any case where you replace a production object or procedure with another for testing purposes. In automated unit testing, a test double replaces an object on which the System Under Test (SUT) depends on.

Test doubles are popularly (and incorrectly) called Mock objects, but in reality, a mock object is a very specific type of test double.

The word "mock" is sometimes used in an informal way to refer to the whole family of objects that are used in tests. They are called test doubles. — Robert C. Martin

…​They were introduced at XP2000 in a paper called Endo-Testing: Unit Testing with Mock Objects, and it took a long time after that for them to gain popularity. Their role in software development was still being fleshed out in 2004 when Mock Roles, Not Objects was published. — TDD, Straw Men, and Rhetoric

The key reason for tests doubles is to help us design how our objects communicate. They help in verifying indirect output of the SUT, by checking that it interacted with it’s (direct or indirect) collaborators in an expected way. We do that by replacing the objects the SUT depends on with doubles that record how they are called, such that, we can check if the SUT interacted with it’s dependencies as expected or not, if it did it at all. This is illustrated in the figure below.

Figure 1. Test code stimulating the SUT and checking expectations on test doubles through a Mockery

Mock objects help us move from state-based testing to interaction-based testing, where rather than looking at the objects' state, we look at their interactions and behaviour. This stops us from having to add unneeded getters to our code just to be able to assert they have the right state.

Another reason we use test doubles is for code isolation (Read the "A warning about over-isolating, specially through Mocking" section below before jumping to conclusions). When we’re testing code that depends on another class, we provide the object with a double instance of that class, instead of a real object. That way, we’re making sure that our test will only fail if the SUT is broken, and not if one of it’s dependencies is broken.

Doubles also allow us to replace/override/patch some functions on objects so that we can ease testing. An example of that is when you have written an encoding algorithm which you want to test. This algorithm uses a function getRandomPrime() from another class (in this example RandomGenerator ). For testing the encoding algorithm you need to know the value of the parameters and the resulting return value for your assertions. To solve the problem, that the return value depends on a random value you can "stub" the class RandomGenerator and tell the function getRandomPrime() to return 7 every time it’s called during the test.

We can also create double objects from interfaces. This makes a lot of sense if we think about it. In many cases, we should actually use doubled interfaces in tests instead of doubled concrete classes. After all, the interface is the contract by which classes agree to talk to the outside world.

Summarizing, the typical reasons for using test doubles may include:

"These getters we write for testing are cluttering up the design", i.e. adding otherwise unnecessary getters to many objects in order to get object state so that we can verify expectations, ultimately cluttering up the design

Difficulties with integration testing - some parts are slow or expensive to test

Non-deterministic behaviour (date & time, web service APIs, pseudo-random functions, etc.)

Dependency on an external resource: FS, DB, net, printer

improve the performance of our tests

real object hasn’t been written yet

what you’re calling has UI/needs human interaction

simplify test setup

build in smaller increments