如何对受保护的方法进行单元测试?

时间:2017-02-07 16:17:45

标签: phpunit

有没有办法对类的受保护或私有方法进行单元测试?就像现在一样,我公开了很多方法,以便能够测试它们,从而打破了API。

修改:实际上已在此处回答:Best practices to test protected methods with PHPUnit

2 个答案:

答案 0 :(得分:3)

您可以先使用ReflectionMethod类,再使用invoke方法来访问私有和/或受保护的方法,但是要调用该方法,您还需要一个类的实例,在某些情况下该实例是“不可能的。基于这个有效的示例,这个示例是这样的:

模拟课堂情况:

$mockedInstance = $this->getMockBuilder(YourClass::class)
        ->disableOriginalConstructor()    // you may need the constructor on integration tests only
        ->getMock();

让您的方法得到测试:

$reflectedMethod = new \ReflectionMethod(
    YourClass::class,
    'yourMethod'
);

$reflectedMethod->setAccessible(true);

调用您的私有/受保护方法:

$reflectedMethod->invokeArgs(    //use invoke method if you don't have parameters on your method
    $mockedInstance, 
    [$param1, ..., $paramN]
);

答案 1 :(得分:0)

对于受保护的方法,您可以对测试中的类进行子类化:

class Foo 
{
    protected function doThings($foo) 
    {
        //...
    }
}


class _Foo extends Foo 
{
    public function _doThings($foo) 
    {
        return $this->doThings($foo);
    }
} 

并且在测试中:

$sut = new _Foo();
$this->assertEquals($expected, $sut->_doThings($stuff));

使用私有方法会有点困难,您可以使用Reflection API来调用受保护的方法。此外,有一种观点认为私有方法应该只在重构期间出现,所以应该由调用它们的公共方法覆盖,但只有在测试优先开始时才能真正起作用,并且在现实生活中我们有遗留代码处理;)

反射api的链接:

http://php.net/manual/en/reflectionmethod.setaccessible.php

此外,此链接看起来很有用:

https://jtreminio.com/2013/03/unit-testing-tutorial-part-3-testing-protected-private-methods-coverage-reports-and-crap/