PHPUnit "Мошеннический метод не существует". при использовании $mock-> expects ($ this-> at (...))
У меня возникла странная проблема с объектами макета PHPUnit. У меня есть метод, который следует вызывать дважды, поэтому я использую "at" matcher. Это работает в первый раз, когда метод вызывается, но по какой-то причине, во второй раз, когда он вызывался, я получаю "Mocked method does not exist.". Раньше я использовал совпадение "at" и никогда не сталкивался с этим.
Мой код выглядит примерно так:
class MyTest extends PHPUnit_Framework_TestCase
{
...
public function testThis()
{
$mock = $this->getMock('MyClass', array('exists', 'another_method', '...'));
$mock->expects($this->at(0))
->method('exists')
->with($this->equalTo('foo'))
->will($this->returnValue(true));
$mock->expects($this->at(1))
->method('exists')
->with($this->equalTo('bar'))
->will($this->returnValue(false));
}
...
}
Когда я запускаю тест, я получаю:
Expectation failed for method name is equal to <string:exists> when invoked at sequence index 1.
Mocked method does not exist.
Если я удаляю второй матчи, я не получаю ошибку.
Кто-нибудь сталкивался с этим раньше?
Спасибо!
Ответы
Ответ 1
Проблема закончилась тем, что я понял, что "at" подходит для работы. Кроме того, мой пример не был дословным, как он находится в моем unit test. Я думал, что счетчик совпадений "at" работал на основе каждого запроса, где он действительно работает на основе каждого объекта.
Пример:
class MyClass {
public function exists($foo) {
return false;
}
public function find($foo) {
return $foo;
}
}
Неправильно:
class MyTest extends PHPUnit_Framework_TestCase
{
public function testThis()
{
$mock = $this->getMock('MyClass');
$mock->expects($this->at(0))
->method('exists')
->with($this->equalTo('foo'))
->will($this->returnValue(true));
$mock->expects($this->at(0))
->method('find')
->with($this->equalTo('foo'))
->will($this->returnValue('foo'));
$mock->expects($this->at(1))
->method('exists')
->with($this->equalTo('bar'))
->will($this->returnValue(false));
$this->assertTrue($mock->exists("foo"));
$this->assertEquals('foo', $mock->find('foo'));
$this->assertFalse($mock->exists("bar"));
}
}
Правильно:
class MyTest extends PHPUnit_Framework_TestCase
{
public function testThis()
{
$mock = $this->getMock('MyClass');
$mock->expects($this->at(0))
->method('exists')
->with($this->equalTo('foo'))
->will($this->returnValue(true));
$mock->expects($this->at(1))
->method('find')
->with($this->equalTo('foo'))
->will($this->returnValue('foo'));
$mock->expects($this->at(2))
->method('exists')
->with($this->equalTo('bar'))
->will($this->returnValue(false));
$this->assertTrue($mock->exists("foo"));
$this->assertEquals('foo', $mock->find('foo'));
$this->assertFalse($mock->exists("bar"));
}
}
Ответ 2
FYI, Не уверен, что это связано, но я столкнулся с тем же, но не с методом $this->at()
, для меня это был метод $this->never()
.
Это привело к ошибке
$mock->expects($this->never())
->method('exists')
->with('arg');
Исправлена ошибка
$mock->expects($this->never())
->method('exists');
Проделал то же самое при использовании метода $this->exactly(0)
.
Надеюсь, что это поможет кому-то.
Ответ 3
Попробуйте изменить $this->at(1)
на $this->at(2)
Ответ 4
Это печальная формулировка сообщения об ошибке с помощью PHPUnit.
Дважды проверьте порядок ваших вызовов, например, @rr answer.
Для меня, насколько я знаю, с моим собственным кодом, я должен использовать at(0)
и at(1)
соответственно, но это было только до тех пор, пока я не использовал at(2)
и at(3)
вместо этого, чтобы он работал. (Я использую сессию, издевающуюся над CakePHP.)
Лучший способ проверить порядок - получить "в" вызываемый метод и проверить, что прошло. Вы можете сделать это вот так:
$cakePost = $this->getMock('CakePost');
$cakePost->expects($this->once())
->method('post')
->with(
// Add a line like this for each arg passed
$this->callback(function($arg) {
debug("Here what was passed: $arg");
})
);
Ответ 5
Насколько я могу судить по демо-коду, он должен работать. Я подготовил рабочий пример, если вы используете более раннюю версию PHPUnit и хотите проверить этот способ, если он работает и для вас.
В случае, если это не поможет, возможно, вы могли бы предоставить немного больше (в лучшем случае исполняемый) код?:)
<?php
class MyTest extends PHPUnit_Framework_TestCase
{
public function testThis()
{
$mock = $this->getMock('MyClass');
$mock->expects($this->at(0))
->method('exists')
->with($this->equalTo('foo'))
->will($this->returnValue(true));
$mock->expects($this->at(1))
->method('exists')
->with($this->equalTo('bar'))
->will($this->returnValue(false));
$this->assertTrue($mock->exists("foo"));
$this->assertFalse($mock->exists("bar"));
}
}
class MyClass {
public function exists($foo) {
return false;
}
}
Печать
phpunit MyTest.php
PHPUnit 3.4.15 by Sebastian Bergmann.
.
Time: 0 seconds, Memory: 4.25Mb
OK (1 test, 3 assertions)
Ответ 6
Вы уверены, что включили MyClass в свой тест? У меня были некоторые ошибки метода undefined при смехе класса/интерфейса без его включения.