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

Ben Waine picture Ben Waine · Oct 31, 2011 · Viewed 19.1k times · Source

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?

Answer

Gordon picture Gordon · Oct 31, 2011

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