Last active
November 1, 2018 19:31
-
-
Save teklakct/f88832189cdfb9631bfa3a2b0e90dbe6 to your computer and use it in GitHub Desktop.
Simple example why you should make an interface over DateTime
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
interface Clock | |
{ | |
public function now(): \DateTimeInterface; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
class DoIt | |
{ | |
private $clock; | |
private $deps; | |
public function __construct(Clock $clock, SomeDependency $deps) | |
{ | |
$this->clock = $clock; | |
$this->deps = $deps; | |
} | |
public function doSomething(): void | |
{ | |
if ($this->clock->now() > (new \DateTimeImmutable('2018-11-01 01:00:00'))) { | |
$this->deps->run(); | |
} | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
use PhpSpec\ObjectBehavior; | |
class DoItSpec extends ObjectBehavior | |
{ | |
private $now; | |
public function let(Clock $clock, SomeDependency $deps) | |
{ | |
$this->beConstructedWith($clock, $deps); | |
} | |
public function it_do_something_depends_on_time(Clock $clock, SomeDependency $deps) | |
{ | |
$clock->now()->willReturn((new \DateTimeImmutable('2020-12-01 01:00:00'))); | |
$deps->run()->shouldBeCalled(); | |
$this->doSomething(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
final class MockableClock implements Clock | |
{ | |
private $currentTime = null; | |
private $clock; | |
public function __construct(Clock $clock) | |
{ | |
$this->clock = $clock; | |
} | |
public function now(): \DateTimeInterface | |
{ | |
if ($this->currentTime) { | |
return $this->currentTime; | |
} | |
return $this->clock->now(); | |
} | |
public function set(\DateTimeInterface $time): void | |
{ | |
$this->currentTime = $time; | |
} | |
public function reset(): void | |
{ | |
$this->currentTime = null; | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
final class Something | |
{ | |
private $clock; | |
public function __construct(Clock $clock) | |
{ | |
$this->clock = $clock; | |
} | |
/** | |
* Good way. It easily testable | |
*/ | |
public function beforeMidday(): bool | |
{ | |
return (int) $this->format('Hi') < 1200); | |
} | |
/** | |
* This method cannot be tested. It depends on time when test is run. | |
*/ | |
public function afterMidday(): bool | |
{ | |
return (int) (new \DateTimeImmutable())->format('Hi') > 1200); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
class SomethingTest | |
{ | |
/** | |
* @dataProvider getTestCases | |
* @test | |
*/ | |
public function checks_that_current_time_is_before_midday($expected, $currentTime) | |
{ | |
$systemClock = new SystemClock(); | |
$clock = new MockableClock($systemClock); | |
$something = new Something($clock); | |
$something->set($currentTime); | |
$this->assertEquals($something->beforeMidday(), $expected); | |
} | |
public function getTestCases() | |
{ | |
return [ | |
[true, (new \DateTimeImmutable('2018-11-01 01:00:00'))], | |
[true, (new \DateTimeImmutable('2018-11-01 11:59:59'))], | |
[false, (new \DateTimeImmutable('2018-11-01 12:00:00'))], | |
[false, (new \DateTimeImmutable('2018-11-01 22:22:22'))], | |
] | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<?php | |
declare(strict_types=1); | |
final class SystemClock implements Clock | |
{ | |
public function now(): \DateTimeInterface | |
{ | |
return new \DateTimeImmutable(); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment