我有一个关于使用PHPUnit模拟类中的私有方法的问题。让我举一个例子:
class A { public function b() { // some code $this->c(); // some more code } private function c(){ // some code } }
我该如何对私有方法的结果进行存根测试以测试公共函数的 更多代码 部分。
通常,您只是不直接测试或嘲笑私有和受保护的方法。
您要测试的是您的类的 公共 API。其他所有内容都是您的类的实现细节,并且如果更改它,则不应“破坏”您的测试。
当您发现“无法获得100%的代码覆盖率”时,这也对您有所帮助,因为您的类中可能包含无法通过调用公共API执行的代码。
但是,如果您的课程如下所示:
class a { public function b() { return 5 + $this->c(); } private function c() { return mt_rand(1,3); } }
我可以看到需要模拟c()的需求,因为“随机”函数是全局状态,您无法对其进行测试。
“干净” /“冗长” //可能过于复杂//“通常”
class a { public function __construct(RandomGenerator $foo) { $this->foo = $foo; } public function b() { return 5 + $this->c(); } private function c() { return $this->foo->rand(1,3); } }
现在,不再需要模拟“ c()”,因为它不包含任何全局变量,并且可以很好地进行测试。
如果您不想执行或无法从私有函数中删除全局状态(不好的事情,坏现实,或者您对坏的定义可能有所不同),则 可以 对模拟 进行 测试。
// maybe set the function protected for this to work $testMe = $this->getMock("a", array("c")); $testMe->expects($this->once())->method("c")->will($this->returnValue(123123));
并针对此模拟运行测试,因为您取出/模拟的唯一函数是“ c()”。
引用“实用单元测试”这本书:
“总的来说,您不想为了测试而破坏任何封装(或者就像妈妈曾经说过的那样,“不要公开您的私人信息!”)。大多数时候,您应该能够测试一门课程通过行使其公开方法。如果在私有访问或受保护的访问后面隐藏着重要的功能,则可能是一个警告信号,表明其中还有另一个类别正在努力摆脱困境。”