我正在为一个类方法编写单元测试,该方法使用mock调用另一个类的方法,只需要调用的方法被声明为final,因此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提供的解决方案,你有一个setter / getter用于你正在模拟的对象进行类型检查(为了确保将正确的对象传递给setter),你需要模拟你正在测试的类中的getter,让它返回另一个mock。
示例:
要被嘲笑的课
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();
}
}
答案 0 :(得分:14)
我不认为PHPUnit支持最终方法的存根/模拟。你可能必须为这种情况创建自己的存根并做一些扩展技巧:
class myTestClassMock {
public function needsToBeCalled() {
$foo = new Class_To_Mock();
$result = $foo->needsToBeCalled();
return array('option');
}
}
下的PHPUnit手册中找到了这个
<强>限制强>
请注意,无法对最终,私有和静态方法进行存根或模拟。它们被PHPUnit的测试双重功能忽略,并保留其原始行为。
答案 1 :(得分:5)
我今天偶然发现了这个问题。另一种方法是模拟类实现的接口,假设它实现了一个接口,并将接口用作类型提示。
例如,考虑到问题,您可以创建一个界面并按如下方式使用它:
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'));
...
}
}