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 (che cita Gerard Meszaros da “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.
che utilizzano Stub e Fake verificano solitamente lo stato del System Under Test e dei collaboratori coinvolti. • Non sempre agire sui SUT comporta dei cambiamenti di stato verificabili, può inoltre capitare che si aggiunga codice solo per poter verificare lo stato stesso nel test. • I test che utilizzano Mock e Spy si concentrano sul comportamento del SUT nei confronti dei collaboratori. • Definire i comportamenti attesi prima di agire sui SUT “sovverte” lo schema tradizionale given-when-then o arrange- act-assert, sostituendolo con qualcosa di più simile ad un arrange-expect-act.
stato è più facile quando si hanno chiari i componenti del sistema e i loro comportamenti, e i test double vengono utilizzati spesso solo per gli oggetti “di confine” (che parlano con la rete, con il database, etc.). • Uno stub sostituisce solitamente un componente già implementato, favorendo quindi un approccio “dal basso”. • Concentrarsi sui comportamenti è incoraggiato quando si vogliono sfruttare i test come strumento di design, per costruire gli elementi del sistema a partire da esempi di utilizzo. • In caso di TDD, un mock propone un’ipotesi (o una profezia) su un componente ancora non implementato (need-driven o outside-in).
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