Подтвердить что ты не робот

Создание макета в 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".

Каким будет правильный способ сделать это?

4b9b3361

Ответ 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);