Slide 1

Slide 1 text

TDD 101 5. Low cost techniques for doubles

Slide 2

Slide 2 text

Low cost techniques for doubles

Slide 3

Slide 3 text

The point of going low-cost Test should be • Light • Fast • Easy to read • Easy to maintain

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

Low cost techniques

Slide 6

Slide 6 text

Techniques at a glance Don’t double (if you don’t really need it) Self shunt Anonymous class

Slide 7

Slide 7 text

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)

Slide 8

Slide 8 text

Don’t double $request = new GetObjectsRequest (‘param1’, ‘param2’); $serviceUnderTest = new Service(); $result = $serviceUnderTest->execute($request); $this->assertEquals(‘expected’, $result);

Slide 9

Slide 9 text

Self-shunt Use the TestCase as double (WTF!) Great for simple doubles Great for early stages of TDD

Slide 10

Slide 10 text

Self-shunt You will need an interface to double Make the test double implement interface You can implement spies

Slide 11

Slide 11 text

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’; } }

Slide 12

Slide 12 text

Self-shunt spy interface CollaboratorInterface { public function doThatThing(): string; } We will need a collaborator for our service

Slide 13

Slide 13 text

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’; } }

Slide 14

Slide 14 text

Anonymous class Create doubles on the fly Code exactly what you need Test Abstract classes Doesn’t require a framework

Slide 15

Slide 15 text

Anonymous class Implement interface or subclass May use builders

Slide 16

Slide 16 text

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()); } }

Slide 17

Slide 17 text

No content