Test doubles
Tien Vo Xuan
Drupal Developer
Go1
What's in this topic
- What is test doubles?
- 5 kinds of test doubles by examples
- How to recognize them?
Test double
or Mock
or Stunt Double (in movies)

Just one thing
When we are writing a test in which we cannot (or chose not to) use a real
depended-on component (DOC), we can replace it with a Test Double. The
Test Double doesn't have to behave exactly like the real DOC; it merely
has to provide the same API as the real one so that the system-under-test (SUT) thinks it is
the real one!
Gerard Meszaros
application

Kinds of double
- Dummy
- Fake
- Stubs
- Spies
- Mocks
Kinds of double

Dummy
objects are passed around but never actually used. Usually they are just used to fill parameter lists.

Dummy
classCarController {functiongetReadyToGo(EngineInterface$engine, GearboxInterface$gearbox, ElectronicsInterface $electronics,LightsInterface$lights) {$engine->start();$gearbox->shift('N');$electronics->turnOn($lights);returntrue;}}
Dummy
$light = $this->getMock('LightInterface');
Dummy
- It does not matter how many times a method is called
- It return null
fake
- It does not matter how many times a method is called
- It does not return null
Fake
$statusPanel = $this->getMock('StatusPanel')
->expects($this->any())
->method('getCurrentSpeed')
->will($this->returnCallback(
function() use ($distance, $time) {
return $distance / $time;
}
));
Stub

stub
functiongoForward(Electronics$electronics, StatusPanel$statusPanel= null) {$statusPanel=$statusPanel? :newStatusPanel();if($statusPanel->engineIsRunning() &&$statusPanel->thereIsEnoughFuel())$electronics->accelerate();}
stub
$stubStatusPanel=$this->getMock('StatusPanel')->expects($this->any()) ->method('thereIsEnoughFuel') ->will($this->returnValue(TRUE));$stubStatusPanel->expects($this->any()) ->method('engineIsRunning')->will($this->returnValue(TRUE));
Stub
- It does not matter which arguments are provided when one of its methods is called.
- It does not matter how many times a method is called.
- It return a fixed value.
spy
- Keep track of method being called.
- To later examine.
Spy
$currentDirection = null;
$carSpy = $this->getMock('CarController');
$carSpy->expects($this->any())
->method('turnLeft')
->will($this->returnCallback(
function() use(&$currentDirection) {
$currentDirection = 'left';
}
));
// turn right ...
Spy
$remote = new Remote($carSpy);
$remote->turnRight();
$remote->turnLeft();
// ...
$this->assertEquals('right', $currentDirection);
mock
- Just like Spy
- Also: Make sure that the methods were called the expected number of times, in a particular order, with the correct arguments.
mock
$carMock = $this->getMock('CarController');
$carMock->expects($this->at(0))
->method('turnLeft')
->with(30);
$carMock->expects($this->at(1))
->method('turnLeft')
->with(20);
$carMock->expects($this->at(0))
->method('turnRight')
->with(15);
Mock
$remote = new Remote($carMock);
$remote->turnLeft(30);
$remote->turnLeft(20);
$remote->turnRight(15);
mock
The mock is not so interested in the return values of functions. It's more interested in what function were called, with what arguments, when, and how often.
Recognize
- Dummy: neither expects() or method() or with() or will()
- Stub: expects($this->any()) and will($this->returnValue('static value'))
- Fake: expects($this->any()) and will($this->returnCallBack('a callback'));
- Spy: expects($this->any()) and will($this->returnCallBack('use and assign value to global variables'));
- Mock: expects(either at or once or exactly or atLeastOnce or never) and with('arguments') and without will()
references
Q&A
Test double
By Tiến Võ Xuân
Test double
- 1,294