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

Low cost techniques for test doubles

Low cost techniques for test doubles

Fran Iglesias

November 02, 2018
Tweet

More Decks by Fran Iglesias

Other Decks in Programming

Transcript

  1. The point of going low-cost Test should be • Light

    • Fast • Easy to read • Easy to maintain
  2. The point of going low-cost Reduce dependency on mocking frameworks

    Strictly speaking, mocking frameworks break isolation principle Use the things you have at hand
  3. Don’t double Use real objects when: • They have no

    behavior or it is very simple • They have no side effects • They are immutable • They have no dependencies (or depend on similar objects)
  4. Don’t double $request = new GetObjectsRequest (‘param1’, ‘param2’); $serviceUnderTest =

    new Service(); $result = $serviceUnderTest->execute($request); $this->assertEquals(‘expected’, $result);
  5. Self-shunt You will need an interface to double Make the

    test double implement interface You can implement spies
  6. Self-shunt stub Class ServiceTest extends TestCase implements GetObjectsRequestInterface { public

    function testSomething() { $serviceUnderTest = new Service(); $result = $serviceUnderTest->execute($this); $this->assertEquals(‘expected’, $result); } public function param1() { return ‘param1’; } public function param2() { return ‘param2’; } }
  7. Self-shunt spy class ServiceTest extends TestCase 
 implements CollaboratorInterface {

    private $collaboratorCalls = 0; public function testSomething() { $serviceUnderTest = new Service($this); $result = $serviceUnderTest->execute(); $this->assertEquals(‘expected’, $result); $this->assertEquals(1, $this->collaboratorCalls); } public function doThatThing(): string { $this->collaboratorCalls+; return ‘something’; } }
  8. Anonymous class Create doubles on the fly Code exactly what

    you need Test Abstract classes Doesn’t require a framework
  9. Anonymous class class ServiceTest extends TestCase { public function testSomething()

    { $collaborator = new class ()
 implements CollaboratorInterface { private $calls = 0; public function doThatThing(): string { $this->calls++; return ‘something’; } public function calls() { return $this->calls; } }; $serviceUnderTest = new Service($collaborator); $result = $serviceUnderTest->execute(); $this->assertEquals(‘expected’, $result); $this->assertEquals(1, $collaborator->calls()); } }