Создание макета в phpunit без насмешек какими-либо методами? - PullRequest
36 голосов
/ 22 февраля 2012

Когда я тестирую мой 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() with:

$obj = new Foobar();
$this->assertTrue($obj->myMethod('abcd'));

Но это вызвало бы конструктор Foobar, который я не хочу.Поэтому вместо этого я бы попробовал:

$obj = $this->getMockBuilder('Foobar')->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));

Но вызов getMockBuilder() без использования setMethods() приведет к тому, что все его методы будут смоделированы и вернут ноль, поэтому мой вызов myMethod() вернет ноль безкасаясь кода, который я собираюсь проверить.

Мой обходной путь до сих пор был таким:

$obj = $this->getMockBuilder('Foobar')->setMethods(array('none'))
    ->disableOriginalConstructor()->getMock();
$this->assertTrue($obj->myMethod('abcd'));

Это будет издеваться над методом с именем 'none', который не существует, но PHPUnit не делаетвсе равно.Он оставит myMethod () без изменений, чтобы я мог его вызвать, и также позволит отключить конструктор, чтобы я не вызывал его.Отлично!За исключением того, что кажется обманом необходимость указывать имя метода, который не существует - «none», или «blargh», или «xyzzy».

Что было бы правильным способом сделать это

Ответы [ 4 ]

46 голосов
/ 22 февраля 2012

Вы можете передать null на setMethods(), чтобы избежать насмешек над любыми методами. Передача пустого массива будет издеваться над всеми методами. Последний является значением по умолчанию для методов, которые вы нашли.

При этом я бы сказал, что необходимость сделать это может указать на недостаток в дизайне этого класса. Должен ли этот метод быть статическим или перемещен в другой класс? Если метод не требует полностью сконструированного экземпляра, это признак того, что это может быть служебный метод, который можно сделать статическим.

3 голосов
/ 24 февраля 2012

Еще одно хакерское, но краткое решение - просто перечислить магический конструктор в качестве одного из проверенных методов:

$mock = $this->getMock('MyClass', array('__construct'));
0 голосов
/ 22 декабря 2015

Или вы можете просто использовать getMock() напрямую.

$mock = $this->getMock('MyClass', null, array(), null, false);

0 голосов
/ 28 февраля 2012

Это сработало для меня:

$this->getMock($class, array(), array(), '', false);
...