... not knowing if \'mock\' is the right word.
Anyway, I have an inherited code-base that I\'m trying to write some tests for that are time-based. Trying not to be <
For those of you working with symfony (>= 2.8): Symfony's PHPUnit Bridge includes a ClockMock feature that overrides the built-in methods time
, microtime
, sleep
and usleep
.
See: http://symfony.com/doc/2.8/components/phpunit_bridge.html#clock-mocking
Simplest solution would be to override PHP time() function and replace it with your own version. However, you cannot replace built-in PHP functions easily (see here).
Short of that, the only way is to abstract time() call to some class/function of your own that would return the time you need for testing.
Alternatively, you could run the test system (operating system) in a virtual machine and change the time of the entire virtual computer.
You can overide php's time() function using the runkit extension. Make sure you set runkit.internal_overide to On
I had to simulate a particular request in future and past date in the app itself (not in Unit Tests). Hence all calls to \DateTime::now() should return the date that was previously set throughout the app.
I decided to go with this library https://github.com/rezzza/TimeTraveler, since I can mock the dates without altering all the codes.
\Rezzza\TimeTraveler::enable();
\Rezzza\TimeTraveler::moveTo('2011-06-10 11:00:00');
var_dump(new \DateTime()); // 2011-06-10 11:00:00
var_dump(new \DateTime('+2 hours')); // 2011-06-10 13:00:00
Here's an addition to fab's post. I did the namespace based override using an eval. This way, I can just run it for tests and not the rest of my code. I run a function similar to:
function timeOverrides($namespaces = array()) {
$returnTime = time();
foreach ($namespaces as $namespace) {
eval("namespace $namespace; function time() { return $returnTime; }");
}
}
then pass in timeOverrides(array(...))
in the test setup so that my tests only have to keep track of what namespaces time() is called in.