Stubbing and Mocking Static Methods
This article is part of a series on testing untestable code:
- Testing private methods
- Testing code that uses singletons
- Stubbing static methods
- Stubbing hard-coded dependencies
With PHPUnit 3.5 it will be possible to stub and mock static methods.
Consider the class Foo:
<?php
class Foo
{
public static function doSomething()
{
return static::helper();
}
public static function helper()
{
return 'foo';
}
}
?>
When testing Foo::doSomething() we want to decouple it from its dependency Foo::helper(). With PHPUnit 3.5 and PHP 5.3 as well as consistent use of late static binding (using static:: instead of self::) the following is possible:
<?php
class FooTest extends PHPUnit_Framework_TestCase
{
public function testDoSomething()
{
$class = $this->getMockClass(
'Foo', /* name of class to mock */
array('helper') /* list of methods to mock */
);
$class::staticExpects($this->any())
->method('helper')
->will($this->returnValue('bar'));
$this->assertEquals(
'bar',
$class::doSomething()
);
}
}
?>
The new staticExpects() method works similar to the non-static expects() variant.
This approach only works for the stubbing and mocking of static method calls where caller and callee are in the same class. This is because static methods are death to testability:
"Unit-Testing needs seams, seams is where we prevent the execution of normal code path and is how we achieve isolation of the class under test. Seams work through polymorphism, we override/implement class/interface and then wire the class under test differently in order to take control of the execution flow. With static methods there is nothing to override. Yes, static methods are easy to call, but if the static method calls another static method there is no way to override the called method dependency."
12/02/2010 at 10:55 Permalink
I understand there can be things outside of your control, but in this day and age... Call me narrow minded, but things which hurt testability should be swept into a corner and quietly suffocated in their own global state.
Sebastian, would you mind elaborating on why you are being so accommodating? IE you seem to be investing a fair amount of time into making the hard/crap to test code of the world a bit more testable, but in the long run "approving" it.
Reply
13/02/2010 at 06:40 Permalink
Reply
12/02/2010 at 13:30 Permalink
Reply
12/02/2010 at 17:42 Permalink
Reply
21/01/2011 at 00:04 Permalink
http://downloads.php.net/pierre/
Mike
Reply