Most of the answers I saw in StackOverflow do not use the DateTime object and instead use the date() function. This makes them very dirty decisions (redefinition of date() , mockery of the protected function of the subject, etc.).
Is there a way to mock DateTime by effectively mocking the current date / time?
As an example, here is the code I would like to test:
public function __construct(UserInterface $user, EntityManager $manager) { $this->user = $user; $this->manager = $manager; } public function create(Tunnel $tunnel, $chain, $response) { $history = new CommandHistory(); $history->setTunnel($tunnel) ->setCommand($chain) ->setResponse($response) ->setUser($this->user) ; $this->manager->persist($history); $this->manager->flush(); }
Here I set the date and time in the CommandHistory class:
class CommandHistory {
And here is my unit test:
public function testCreate() { $user = new User(); $manager = $this->mockManagerWithUser($user); $tunnel = $this->tunnel; $chain = 'Commands`Chain'; $response = 'This is the response!'; $creator = new CommandHistoryCreator($user, $manager); $creator->create($tunnel, $chain, $response); } protected function mockManagerWithUser(UserInterface $user) { $manager = \Mockery::mock('Doctrine\ORM\EntityManager'); $manager->shouldReceive('persist')->once()->with(\Mockery::on(function(CommandHistory $argument) use ($user) { return $argument->getCommand() === 'Commands`Chain' && $argument->getResponse() === 'This is the response!' && $argument->getTunnel() === $this->tunnel && $argument->getUser() === $user ; })); $manager->shouldReceive('flush')->once()->withNoArgs(); return $manager; }
As you can see, I created a rather long closure just to exclude comparing the field that contains the current time, and I feel that this affects the readability of my test.
Also, in order to maintain ease of use for people who use this class, I do not want them to switch to the create() function at the current time. I believe that adding weird behavior to my classes just to make them testable means that I'm doing something wrong.
source share