С введением позднего статического связывания в PHP 5.3 появилась возможность красиво протестировать статические методы тестируемого класса.
Допустим у нас есть класс Foo, с двумя методами doSomething() и prefix(). Последний статический и вызывается внутри doSomething().
1 2 3 4 5 6 7 8 9 10 11 12 |
class Foo {
public function doSomething($var)
{
$prefix = static::prefix();
return $prefix . $var;
}
public static function prefix()
{
return 'foo';
}
} |
Хочу обратить внимание на строчку #4. Здесь используется static:: вместо self::
Задача:
Подменить выполнение статического метода prefix() внутри doSomething().
Решение:
Создаем мок на тестируемый класс. Для него генерируется уникальное имя, которое мы извлекаем с помощью getMockClass(). Используем staticExpects() для подмены результата вызова статического метода.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class FooTest extends PHPUnit_Framework_TestCase {
public function testDoSomething()
{
$foo = $this->getMock('Foo', array('prefix'));
$class = $this->getMockClass('Foo', array('prefix'));
$class::staticExpects($this->any())
->method('prefix')
->will($this->returnValue('bar'));
$this->assertEquals('bar9', $foo->doSomething('9'));
}
} |
По сути staticExpects() является аналогом expects() только для статических классов. Единственное (и одно из самых главных) ограничений заключается в том, что мокнуть статический метод можно только внутри тестируемого класса. Это еще один минус в пользу использования статических методов.
Еще одно похожее решение:
Можно еще воспользоваться строителем мока
1 2 3 4 5 6 7 8 9 10 11 12 |
public function testDoSomething3()
{
$foo = $this->getMockBuilder('Foo')
->setMethods(array('prefix'))
->getMock();
$foo::staticExpects($this->any())
->method('prefix')
->will($this->returnValue('bar'));
$this->assertEquals('bar9', $foo->doSomething('9'));
} |
Источник: http://sebastian-bergmann.de/archives/883-Stubbing-and-Mocking-Static-Methods.html