Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Tests doubles: the motion picture

Tests doubles: the motion picture

Test doubles explained

Fran Iglesias

November 02, 2018
Tweet

More Decks by Fran Iglesias

Other Decks in Programming

Transcript

  1. A unit of software Can be a query: returns a

    response Can be a command: produces a change in the state of the system You should test the results of the behavior
  2. When you test it You want to prove that the

    behavior: • Is produced by the code of the unit of software • Is not influenced by any other factor
  3. So, you need to control the behavior of collaborators Cancelling:

    no behavior at all Controlling: knowing exactly what they are doing (by means of programming it)
  4. namespace Tests\Dojo\HappyBirthday; use Dojo\HappyBirthday\SendGreetings; use PHPUnit\Framework\TestCase; class SendGreetingsTest extends TestCase

    { public function testSendGreetingToCustomersWhenIsTheirBirthday() { $clockService = $this->getClockServiceStub(); $logger = $this->getLoggerDummy(); $customerRepository = $this->getCustomerRepositoryStub(); $mailer = $this->getMailerSpy([ new Customer('[email protected]'), new Customer('[email protected]'), new Customer('[email protected]') ]); $sendGreetings = new SendGreetings( $clockService, $customerRepository, $mailer, $logger ); $sendGreetings->execute(); $this->assertEquals(3. $mailer->getMessagesSent()); } }
  5. namespace Tests\Dojo\HappyBirthday\Double; use DateTimeImmutable; use Dojo\HappyBirthday\Clock\ClockService; class ClockServiceStub implements ClockService

    { /** @var DateTimeImmutable */ private $dateTime; public function __construct(DateTimeImmutable $dateTime) { $this->dateTime = $dateTime; } public function currentDate() : DateTimeImmutable { return $this->dateTime; } }
  6. namespace Tests\Dojo\HappyBirthday; use Dojo\HappyBirthday\SendGreetings; use PHPUnit\Framework\TestCase; class SendGreetingsTest extends TestCase

    { public function testSendGreetingToCustomersWhenIsTheirBirthday() { $clockService = $this->getClockServiceStub(); $logger = $this->getLoggerDummy(); $customerRepository = $this->getCustomerRepositoryStub(); $mailer = $this->getMailerSpy([ new Customer('[email protected]'), new Customer('[email protected]'), new Customer('[email protected]') ]); $sendGreetings = new SendGreetings( $clockService, $customerRepository, $mailer, $logger ); $sendGreetings->execute(); $this->assertEquals(3. $mailer->getMessagesSent()); } }
  7. class MailerSpy implements Mailer { private $calls = 0; public

    function send(Message $message) : void { $this->calls++; } public function getCalls() { return $this->calls; } }
  8. test doubles by behavior dummy stub fake no behavior fixed

    complete Applies to any kind of double by knowledge
  9. test doubles by knowledge passive spy mock Applies to any

    kind of double by behavior knows
 nothing registers
 use has
 expectations
  10. i

  11. class ServiceTest extends TestCase implements Mailer { private $mailerCalls =

    0; public function testMailer() { $sut = new Service($this); $sut->execute(); $this->assertEquals(2, $this->getCalls()); } public function send(Message $message) : void { $this->mailerCalls++; } }
  12. class ServiceTest extends TestCase { public function testMailer() { $mailer

    = new class implements Mailer { private $calls = 0; public function send(Message $message) : void { $this->calls++; } puablic function getCalls() { return $this->calls; } }; $sut = new Service($mailer); $sut->execute(); $this->assertEquals(2, $mailer->getCalls()); } }
  13. class ServiceTest extends TestCase { public function testMailer() { $mailer

    = $this->createMock(Mailer::class); $mailer->expects($this->once()) ->method(‘send’) ->with($this->isInstanceOf(Message::class)) ->willReturn(true); $sut = new Service($mailer); $sut->execute(); } }