Я столкнулся со странной проблемой с фиктивными объектами PHPUnit. У меня есть метод, который нужно назвать дважды, таким образом, я использую "в" matcher. Это работает впервые, метод называют, но по некоторым причинам, во второй раз это называют, я получаю "Дразнивший метод, не существует".. Я использовал "в" matcher прежде и никогда не сталкивался с этим.
Мой код смотрит что-то как:
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.
Если я удаляю второй matcher, я не получаю ошибку.
Кто-либо столкнулся с этим прежде?
Спасибо!
Проблема в конечном итоге заключалась в том, как я понял, что сопоставление "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"));
}
}
Насколько я могу судить по демонстрационному коду, он должен работать. Я создал рабочий пример на тот случай, если вы используете более старую версию 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 в свой тест? У меня были некоторые ошибки неопределенного метода при насмешке над классом / интерфейсом без его включения.