Создание макета в phpunit без издевательства над любыми методами?
Когда я тестирую свой PHP-код с помощью PHPUnit, я пытаюсь найти правильный способ издеваться над объектом, не издеваясь над любыми его методами.
Проблема в том, что если я не вызываю getMockBuilder()->setMethods()
, тогда все методы на объекте будут издеваться, и я не могу вызвать метод, который я хочу проверить; но если я звоню setMethods()
, то мне нужно сказать, какой метод издеваться надо мной, но я вообще не хочу издеваться над любыми методами. Но мне нужно создать макет, поэтому я могу избежать вызова конструктора в своем тесте.
Вот тривиальный пример метода, который я хотел бы проверить:
class Foobar
{
public function __construct()
{
// stuff happens here ...
}
public function myMethod($s)
{
// I want to test this
return (strlen($s) > 3);
}
}
Я могу проверить myMethod()
на:
$obj = new Foobar();
$this->assertTrue($obj->myMethod('abcd'));
Но это вызовет конструктор Foobar, который я не хочу. Поэтому вместо этого я попробую:
$obj = $this->getMockBuilder('Foobar')->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));
Но вызов getMockBuilder()
без использования setMethods()
приведет к тому, что все его методы будут издеваться и будут возвращены null, поэтому мой вызов myMethod()
вернет значение null, не касаясь кода, который я намерен проверить.
Мое обходное решение до сих пор было следующим:
$obj = $this->getMockBuilder('Foobar')->setMethods(array('none'))
->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));
Это высмеивает метод с именем "none", которого не существует, но PHPUnit все равно. Он отключит myMethod(), чтобы я мог вызвать его, и он также позволит мне отключить конструктор, чтобы я его не называл. Отлично! За исключением того, что кажется, что обман должен указывать имя метода, которого не существует - "none", или "blargh" или "xyzzy".
Каким будет правильный способ сделать это?
Ответы
Ответ 1
Вы можете передать null
в setMethods()
, чтобы избежать издевательств над любыми методами. Передача пустого массива будет издеваться над всеми методами. Последнее значение по умолчанию для методов, которые вы нашли.
Говоря, я бы сказал, что необходимость сделать это может указывать на недостаток в дизайне этого класса. Должен ли этот метод быть статическим или перемещаться в другой класс? Если для метода не требуется полностью сконструированный экземпляр, это признак для меня, что это может быть метод полезности, который может быть сделан статическим.
Ответ 2
Другое хакерское, но сжатое решение - просто перечислить волшебный конструктор как один из издевающихся методов:
$mock = $this->getMock('MyClass', array('__construct'));
Ответ 3
Или вы можете просто использовать getMock()
напрямую.
$mock = $this->getMock('MyClass', null, array(), null, false);
Ответ 4
Это сработало для меня:
$this->getMock($class, array(), array(), '', false);