我花了一些时间调试对象测试,却发现 PHPUnit 静默地忽略了指定的存根行为,因为该方法尚未在正在存根的类中定义:
<?php
class SomeClass {
public function aMethod()
{
// exists, but no body;
}
}
class someOtherClassTest extends 'PHPUnit_Framework_TestCase
{
public function testSomeDependentClassMethod()
{
$stub = $this->getMock('SomeClass');
$stub->expects($this->once())
->method('aFakeMethod')
->will($this->returnValue('foo'));
// silently returns nothing!
$stub->aFakeMethod();
$stub->expects($this->once())
->method('aMethod')
->will($this->returnValue('bar'));
// as expected, returns 'bar'
$stub->aMethod();
}
}
这是故意的吗?如果是这样,背后的原因是什么?
我在文档中找不到有关此行为的任何内容,但如果打算以这种方式工作,则不想将其报告为错误。
这是一个悬而未决的问题,请参阅以下 GitHub 链接:
https://github.com/sebastianbergmann/phpunit-mock-objects/issues/21
https://github.com/sebastianbergmann/phpunit-mock-objects/issues/12
当你得到模拟方法时,PHPUnit 通过反射获取类的方法,并将这些方法添加到模拟中。 除非您向模拟提供要模拟的方法列表,否则它将使用这些方法并保留其他所有内容。
https://github.com/sebastianbergmann/phpunit-mock-objects/blob/master/src/Framework/MockObject/Generator.php#L741
如果您阻止使用自动加载器加载类,也会发生这种情况。 在这种情况下,不会替换任何方法。
为您的模拟提供您将要模拟的方法列表,这是getMock()
方法的第二个参数。 然后,您将能够存根不存在的方法。 因此,请将测试更改为:
public function testSomeDependentClassMethod()
{
$stub = $this->getMock('SomeClass', ['aFakeMethod', 'aMethod']);
$stub->expects($this->once())
->method('aFakeMethod')
->will($this->returnValue('foo'));
$stub->aFakeMethod();
$stub->expects($this->once())
->method('aMethod')
->will($this->returnValue('bar'));
$stub->aMethod();
}
或者你可以使用getMockBuilder:
public function testSomeDependentClassMethod()
{
$stub = $this->getMockBuilder('SomeClass')
->setMethods(['aFakeMethod', 'aMethod'])
->getMock()
$stub->expects($this->once())
->method('aFakeMethod')
->will($this->returnValue('foo'));
$stub->aFakeMethod();
$stub->expects($this->once())
->method('aMethod')
->will($this->returnValue('bar'));
$stub->aMethod();
}