PHPUnit «Mocked method не существует» при использовании $ mock-> expects ($ this-> at (…))

У меня возникла странная проблема с объектами 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 в свой тест? У меня были некоторые неопределенные ошибки метода, когда насмехались над классом / интерфейсом, не включая его.