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

Проверьте, что mock метод вызывается без каких-либо параметров (в phpunit)

В 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() имеет значения по умолчанию). Поскольку любой параметр не по умолчанию (более точный: любой параметр!= По умолчанию один, который мы еще не знаем и который, возможно, может измениться независимо) в этом случае приводит к фатальным последствиям.

4b9b3361

Ответ 1

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

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

Во-вторых, если ваш метод предоставляет значения по умолчанию, вызов метода без аргументов заставит PHP изменить вызов до того, как PHPUnit будет задействован для передачи значений по умолчанию. Вот простой тест, демонстрирующий PHP, вставляющий себя, прежде чем PHP сможет проверить параметры. Это ключ к пониманию того, что класс mock, созданный 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;
        }
}

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

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

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

Ответ 2

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

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

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

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