У меня возникла странная проблема с объектами PHPUnit mock. У меня есть метод, который следует вызывать дважды, поэтому я использую «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.
Если я удалю второй элемент, я не получу ошибку.
Кто-нибудь сталкивался с этим раньше?
Благодаря!
Проблема закончилась тем, что я понял, что «at» подходит для работы. Кроме того, мой пример не был дословным, как он находится в моем модульном тесте. Я думал, что счетчик совпадений «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")); } }
FYI, Не уверен, если это связано, но я столкнулся с тем же, но не с методом $this->at()
, для меня это был метод $this->never()
.
Это подняло ошибку
$mock->expects($this->never()) ->method('exists') ->with('arg');
Это фиксировало ошибку
$mock->expects($this->never()) ->method('exists');
Он сделал то же самое при использовании метода $this->exactly(0)
.
Надеюсь, это поможет кому-то.
Попробуйте изменить $this->at(1)
на $this->at(2)
Это печальная формулировка сообщения об ошибке PHPUnit.
Дважды проверьте порядок ваших звонков, например, ответ на вопрос @ rr.
Для меня, насколько я знаю, с моим собственным кодом, я должен использовать 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's what was passed: $arg"); }) );
Насколько я могу судить по демо-коду, он должен работать. Я подготовил рабочий пример, если вы используете более раннюю версию 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)
Вы уверены, что включили MyClass в свой тест? У меня были некоторые неопределенные ошибки метода, когда насмехались над классом / интерфейсом, не включая его.