我想测试这个函数:
public function reset()
{
if(!$this->onBeforeReset()) // Protected, internal method
{
return false;
}
// Continue with tests
}
当onBeforeReset
函数也返回false或true时,我希望测试它。
我该怎么做呢?这可能吗?
是否有一种方法可以"模拟"被测试类的某些部分?
是的,除非您想要模拟的方法是私有的或最终的,否则您只能模拟这一个方法。一个例子:
$sut = $this->getMock('Your'Class', array('onBeforeReset'));
getMock
方法的第二个参数是数组,包含phpunit将模拟的方法。如果该数组为空,phpunit将模拟对象中的所有方法,但如果您精确指定了至少一个方法,phpunit将只模拟传入该数组的methodz。
你像往常一样模拟方法:
$sut->expects($this->any())
->method('onBeforeReset')
->will($this->returnValue(true));
最后你可以测试你想测试的方法:
$this->assertWhatever($expectedValue, $sut->reset());
我对单元测试的理解是测试类的公共接口。因此,在您的示例中,您只断言reset()的结果,而不是断言内部调用的所有受保护函数和私有函数。然后从reset()给出的结果推断出onbeforeereset()给出的结果。
这当然不是100%的规则。有时你真的想测试一个私有的或受保护的方法,无论出于什么原因(无论如何要考虑到这可能意味着你实际上应该重构你的代码)。
PHPUnit的创建者写了一些想法并给出了一些例子(http://sebastian-bergmann.de/archives/881-Testing-Your-Privates.html)。基本上,您使用反射使私有和受保护的方法和属性可公开访问。