Mocking global PHP functions in phpunit

20 Jul 2016 in Programming, PHP, phpunit

In order to mock global php functions like date(), rand(), etc, I developed a simple solution utilizing phpunit's getMock() method.

For example, assuming you are trying to mock the date() function, replace the occurences of the function in your class with a call to a new protected method that calls this function and returns the result.

So, the following snippet:

class ExampleClass {
    public function foo() {
        $date = date('Y-m-d H:i:s');
        // do something
        // ...
        return $date;
    }
}

becomes:

class ExampleClass {
    public function foo() {
        $date = $this->date();
        // do something
        // ...
        return $date;
    }
    protected function date() {
        return date('Y-m-d H:i:s');
    }
}

Then, in your tests, instead of creating the actual class, create it via phpunit's getMock() method like this:

// The first parameter is the class name and the second the methods to mock
// Consult phpunit's manual for extra parameters like constructor arguments
$exampleClassInstance = $this->getMock(ExampleClass::class, ["date"]);

Finally, write your tests and set the return value of ExampleClass::date() on each test:

class ExampleClassTest extends PHPUnit_Framework_TestCase {
    protected $sut;
    protected function setUp() {
        $this->sut = $this->getMock(ExampleClass::class, ["date"]);
    }
    public function testFoo() {
        $expected = "2010-01-01 00:00:00";
        $this->sut->expects($this->any())
            ->willReturn($expected)
            ->method("date");
        $actual = $this->sut->foo();
        $this->assertEquals($expected, $actual);
    }
}

This will test the actual class, except mock methods, with code coverage.

Alternative solutions: