Убедитесь, что метод mock вызывается без каких-либо параметров (в phpunit) - PullRequest
13 голосов
/ 28 февраля 2012

В phpunit мы можем указать, что метод был вызван с определенным

->with($this->equalTo('foobar'))

или любой

->with($this->anything())

параметр.

Но есть ли способ указать, что метод был вызван без параметров вообще?

Это тест, который я ожидаю провалить:

public function testZ()
{
    $a = $this->getMock('q');

    $a->expects($this->once())
        ->method('z')
        ->with(); // <--- what constraint to specify here?

    $a->z(1);
}

UPD

Вопрос носит теоретический характер, поэтому у меня нет примеров из реальной жизни. В некоторых случаях это может быть полезно, о чем я могу думать прямо сейчас:

public function testMe($object)
{
    $object->foo();
}

И давайте предположим, что testMe должен (по замыслу и по требованиям) всегда вызывать метод без параметров (при условии, что foo() имеет значения по умолчанию). Потому что любой параметр не по умолчанию (точнее: любой параметр! = Параметр по умолчанию, который мы еще не знаем и который, вероятно, мог бы измениться независимо) в этом случае приводит к фатальным последствиям.

Ответы [ 2 ]

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

Несмотря на то, что rdlowrey прав, что with() не предусматривает проверку на отсутствие переданных аргументов, проблема не в PHPUnit, а в самом PHP.

Во-первых, если ваш метод не предоставляет значений по умолчанию, интерпретатор выдаст фатальную ошибку, если вы не передадите никаких параметров. Это ожидается и не совсем относится к рассматриваемому вопросу, но важно заявить заранее.

Во-вторых, если ваш метод предоставляет значения по умолчанию, вызов метода без аргументов заставит PHP изменить вызов до того, как PHPUnit будет задействован, чтобы вместо него передать значения по умолчанию. Вот простой тест, который демонстрирует вставку PHP перед тем, как PHP сможет проверить параметры. Важно понимать, что создаваемый PHP-класс имеет ту же сигнатуру, что и проверяемый класс, включая значения по умолчанию.

class MockTest extends PHPUnit_Framework_TestCase {
        public function test() {
                $mock = $this->getMock('Foo', array('bar'));
                $mock->expects($this->once())
                     ->method('bar')
                     ->with()    // does nothing, but it doesn't matter
                     ->will($this->returnArgument(0));
                self::assertEquals('foobar', $mock->bar());  // PHP inserts 1 and 2
                // assertion fails because 1 != 'foobar'
        }
}

class Foo {
        public function bar($x = 1, $y = 2) {
                return $x + $y;
        }
}

Это означает, что вы можете проверить, что либо ничего не было передано, либо были переданы значения по умолчанию, но вы не можете быть более конкретным.

Можете ли вы обойти это ограничение? Вы можете удалить значения по умолчанию из аргументов при переопределении методов, так что вы сможете создать подкласс и смоделировать его. Стоит ли оно того? Моя первоначальная внутренняя реакция заключается в том, что это огромный запах кода. Либо ваш дизайн, либо ваши тесты делают неправильно (тм).

Если вы можете предоставить конкретный пример из реальной жизни, в котором вам действительно нужно провести такой тест, стоит потратить некоторое время на обдумывание решения. До тех пор я доволен чисто академическим ответом «не делай этого». :)

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

В фиктивных объектах PHPUnit может использоваться только метод ограничения ->with() для проверки того, что число или соответствующие значения передаваемых параметров соответствуют значениям, передаваемым в проверяемый метод при вызове. Вы не можете использовать его, чтобы потребовать, чтобы без аргументов были переданы в метод mock.

В процессе проверки на ложность проверяется, что количество переданных параметров и соответствующие значения совместимы с теми, которые переданы в ограничение with. Также, как вы, вероятно, видели, указание ограничения with без каких-либо значений также не будет работать; если with не получает параметров, он не добавляет ограничений параметров для проверки.

Вы можете увидеть фактический метод PHPUnit_Framework_MockObject_Matcher_Parameters::verify, используемый для проверки параметров фиктивного метода в связанном источнике github.

Если проверка не переданных аргументов является обязательным требованием, вам необходимо указать свой собственный класс mock для проверки такого условия за пределами возможностей насмешки PHPUnit.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...