Ben Waine Ben Waine - 7 months ago 89
PHP Question

Mocking The Time used by all instances of DateTime for testing purposes.

I'd like to be able to set the time for every instance of DateTime instantiated for the duration of a PHPUnit or Behat Test.

I'm testing business logic relating to time. For example that a method in a class only returns events in the past or future.

Thing's I dont want to do if possible:

1) Write a wrapper around DateTime and use this instead of DateTime throughout my code. This would involve a bit of a re-write of my current code base.

2) Dynamically generate a dataset each time the test / suite is run.

So the question is: Is it possible to override DateTimes behaviour to always supply a specific time when requested?

Answer

You should stub the DateTime methods you need in your tests to return expected values.

    $stub = $this->getMock('DateTime');
    $stub->expects($this->any())
         ->method('theMethodYouNeedToReturnACertainValue')
         ->will($this->returnValue('your certain value'));

See http://www.phpunit.de/manual/3.6/en/test-doubles.html

If you cannot stub the methods because they are hardcoded into your code, have a look at

which explains how to invoke a callback whenever new is invoked. You could then replace the DateTime class with a custom DateTime class that has a fixed time. Another option would be to use http://antecedent.github.io/patchwork