Методы класса PHPUnit Stubbing, объявленные как "окончательные",
Я пишу unit test для метода класса, который вызывает другой метод класса, используя макет, только метод, который нужно вызвать, объявляется окончательным, поэтому PHPUnit не может его издеваться. Есть ли другой подход, который я могу принять?
Пример:
класс, который будет издеваться
class Class_To_Mock
{
final public function needsToBeCalled($options)
{
...
}
}
мой тестовый пример
class MyTest extends PHPUnit_Framework_TestCase
{
public function testDoSomething()
{
$mock = $this->getMock('Class_To_Mock', array('needsToBeCalled'));
$mock->expects($this->once())
->method('needsToBeCalled')
->with($this->equalTo(array('option'));
}
}
Изменить: если вы используете решение, предоставленное Mike B, и у вас есть сеттер/получатель для объекта, который вы издеваетесь, который проверяет тип (чтобы гарантировать, что правильный объект был передан в сеттер), вам нужно высмеять геттер в классе, который вы тестируете, и вернуть его другому макету.
Пример:
класс, который будет издеваться
class Class_To_Mock
{
final public function needsToBeCalled($options)
{
...
}
}
макет
class Class_To_MockMock
{
public function needsToBeCalled($options)
{
...
}
}
проверяемый класс
class Class_To_Be_Tested
{
public function setClassToMock(Class_To_Mock $classToMock)
{
...
}
public function getClassToMock()
{
...
}
public function doSomething()
{
$this->getClassToMock()
->needsToBeCalled(array('option'));
}
}
мой тестовый пример
class MyTest extends PHPUnit_Framework_TestCase
{
public function testDoSomething()
{
$classToTest = $this->getMock('Class_To_Be_Tested', array('getClassToMock'));
$mock = $this->getMock('Class_To_MockMock', array('needsToBeCalled'));
$classToTest->expects($this->any())
->method('getClassToMock')
->will($this->returnValue($mock));
$mock->expects($this->once())
->method('needsToBeCalled')
->with($this->equalTo(array('option'));
$classToTest->doSomething();
}
}
Ответы
Ответ 1
Я не думаю, что PHPUnit поддерживает stubbing/mocking окончательных методов. Возможно, вам придется создать свой собственный заглушку для этой ситуации и сделать некоторые трюки расширения:
class myTestClassMock {
public function needsToBeCalled() {
$foo = new Class_To_Mock();
$result = $foo->needsToBeCalled();
return array('option');
}
}
Обнаружено это в Руководстве по PHPUnit в разделе Глава 11. Тестирование парных разрядов
Ограничения
Обратите внимание, что окончательные, частные и статические методы не могут быть обрезаны или издеваться. Они игнорируются двойными функциональными возможностями PHPUnit и сохраняют свое первоначальное поведение.
Ответ 2
Я только что наткнулся на эту проблему сегодня. Другой альтернативой является издевательство над интерфейсом, который реализует класс, учитывая, что он реализует интерфейс, и вы используете интерфейс как тип намека.
Например, учитывая данную проблему, вы можете создать интерфейс и использовать его следующим образом:
interface Interface_To_Mock
{
function needsToBeCalled($options);
}
class Class_To_Mock implements Interface_To_Mock
{
final public function needsToBeCalled($options)
{
...
}
}
class Class_To_Be_Tested
{
public function setClassToMock(Interface_To_Mock $classToMock)
{
...
}
...
}
class MyTest extends PHPUnit_Framework_TestCase
{
public function testDoSomething()
{
$mock = $this->getMock('Interface_To_Mock', array('needsToBeCalled'));
...
}
}