Tien Vo Xuan
Drupal Developer
Go1
or Mock
or Stunt Double (in movies)
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
objects are passed around but never actually used. Usually they are just used to fill parameter lists.
class
CarController {
function
getReadyToGo(EngineInterface
$engine
, GearboxInterface
$gearbox, ElectronicsInterface $electronic
s,
LightsInterface
$light
s) {
$engine
->start();
$gearbox
->shift(
'N'
);
$electronics
->turnOn(
$lights
);
return
true;
}
}
$light = $this->getMock('LightInterface');
$statusPanel = $this->getMock('StatusPanel')
->expects($this->any())
->method('getCurrentSpeed')
->will($this->returnCallback(
function() use ($distance, $time) {
return $distance / $time;
}
));
function
goForward(Electronics
$electronics
, StatusPanel
$statusPanel
= null) {
$statusPanel
=
$statusPanel
? :
new
StatusPanel();
if
(
$statusPanel
->engineIsRunning() &&
$statusPanel
->thereIsEnoughFuel())
$electronics
->accelerate();
}
$stubStatusPanel
=
$this
->getMock(
'StatusPanel'
)
->expects(
$this
->any()) ->method(
'thereIsEnoughFuel'
) ->will(
$this
->returnValue(TRUE));
$stubStatusPanel->expects($this->any()) ->method('engineIsRunning')
->will($this
->returnValue(TRUE));
$currentDirection = null;
$carSpy = $this->getMock('CarController');
$carSpy->expects($this->any())
->method('turnLeft')
->will($this->returnCallback(
function() use(&$currentDirection) {
$currentDirection = 'left';
}
));
// turn right ...
$remote = new Remote($carSpy);
$remote->turnRight();
$remote->turnLeft();
// ...
$this->assertEquals('right', $currentDirection);
$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);
$remote = new Remote($carMock);
$remote->turnLeft(30);
$remote->turnLeft(20);
$remote->turnRight(15);
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.