Search code examples
phptestingdatetimephpunitbehat

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 don't 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?


Solution

  • 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 https://phpunit.de/manual/current/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