Тестирование статических методов в PHPUnit

С введением позднего статического связывания в 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