as the generic term for any kind of pretend object used in place of a real object for testing purposes. The name comes from the notion of a Stunt Double in movies. Martin Fowler (citing Gerard Meszaros from “xUnitTest Patterns”) “
} /** @test */ public function it_intercepts_secret_messages() { $aMessage = new DummySecretMessage(); $anotherMessage = new DummySecretMessage(); $sut = new SecretAgent(); $sut->intercept($aMessage); $sut->intercept($anotherMessage); $this->assertCount(2, $sut->getInterceptedMessages()); }
test, usually not responding at all to anything outside what's programmed in for the test. Martin Fowler (che cita Gerard Meszaros da “xUnitTest Patterns”) “
some shortcut which makes them not suitable for production (an in memory database is a good example). Martin Fowler (che cita Gerard Meszaros da “xUnitTest Patterns”) “
function add($item) { $this->storage[] = $item; } public function findAll() { return $this->storage; } public function remove($item) { // ... } public function find($id) { // ... } }
on how they were called. One form of this might be an email service that records how many messages it was sent. Martin Fowler (che cita Gerard Meszaros da “xUnitTest Patterns”) “
DummySecretMessage(); $repository = $this->prophesize('TinkerTailor\Repository'); $sut = new SecretAgent($repository->reveal()); $sut->intercept($aMessage); $repository->add($aMessage)->shouldHaveBeenCalled(); $repository->remove(Argument::any())->shouldHaveBeenCalled(); } # phpunit … No calls have been made that match: Double\Repository\P3->remove(*) but expected at least one.
DummySecretMessage(); $repository = $this->prophesize('TinkerTailor\Repository'); $repository->add($aMessage)->shouldBeCalled(); $supervisor = $this->prophesize('TinkerTailor\Supervisor'); $supervisor->authorize()->shouldBeCalled(); $sut = new SecretAgent($repository->reveal()); $sut->intercept($aMessage); } # phpunit … Some predictions failed: Double\TinkerTailor\Supervisor\P5: No calls have been made that match: Double\TinkerTailor\Supervisor\P5->authorize() but expected at least one.
Stubs and Fakes focus verification usually on the state of the System Under Test and involved collaborators. • Not always an action on a sut SUT imples verifiable state changes, and it may happen that extra code is added only to verify state in tests (eg. getters irrelevant to the business logic). • Tests using Mocks and in a way Spies usually focus on the behaviour of the SUT in relation with its collaborators. • Defining expected behaviours before acting on the SUT “subvers” the traditional given-when-then (or arrange- act-assert) test setup, changing it into something more akin to “arrange-expect- act”.
state is easier when a system’s components and their behaviour is clear, and test doubles are often involved in “border” objects (those talking to the network, database, and third party code in general). • A stub often replaces an already implemented component, favouring a “bottom-up” design approach. • Focusing on behaviours is encouraged when you want to use tests as a design tool, to build the elements of a system starting from examples of their usage. • In the case of TDD, a mock offers an hypothesis (or a prophecy) about a not- yet-implemented component (need-driven or outside-in design).
Fowler - Test Double e Mocks Aren't Stubs • Niraj Bhatt - Dummy vs. Stub vs. Spy vs. Fake vs. Mock • Marcelo Duarte - PHP test doubles patterns with prophecy • coderabbi - Making Sense of Test Doubles • Dave Marshall - Mocks Aren't Stubs, Fakes, Dummies or Spies • Konstantin Kudryashov (everzet) - Design How Your Objects Talk Through Mocking • Mockist vs. Classicist TDD • Steve Freeman, Nat Pryce - Growing Object-Oriented Software, Guided by Tests