我对私有/受保护方法的测试存在疑问。这是一个解决任何平台单元测试的一般性问题。但只是告诉你,我正在使用phpunit平台来测试php。
我们应该测试私有/受保护的方法吗?关于此question的接受的答案说我们通常不应该这样做。 从那个答案:
通常你只是不测试或模仿私人&受保护的方法直接。
您要测试的是您班级的公共API。其他一切都是 您的课程的实施细节,如果您更改它,则不会“破坏”您的测试。
但与此同时,许多问题中的其他答案提供了一种测试方法(我假设这些答案意味着我们应该测试私有/受保护的方法,因为它们没有说我们应该或不应该测试它们。) / p>
请原因解释一下。谢谢。
答案 0 :(得分:1)
至于我 - 这取决于私人/受保护成员的复杂程度。
例如,您有私有方法 Func1 ()和 Func2 (),复杂的计算或具有许多输入参数的算法。并且您有一个使用它们的公共API。并且在某些数据 Func1 ()被破坏并返回不正确的数据,但在 Func2 ()处理期间,此数据以某种方式转换为正确的结果(由于其他问题) 。公共API方法的总结果将是正确的 - 这意味着您已经错误地 Func1 和 Func2 ,但您的API会以某种方式重新校正。并且你测试它并且没关系。
现在你给了某人代码,他/她创建了Func3()和另一个使用 Func1 ()和 Func3 ()和单位的公共API方法此API方法的测试失败。他/她将花多少时间找出原因在 Func1 ?当 Func1 将被修复时,您将进行先前的测试 Func2 失败......这完全不好。
所以,恕我直言,你应该测试私有/受保护的方法,如果它们很复杂(很多代码或使用不明显的算法)和可重用。当然,您不需要为返回+ b或编写调试日志记录的私有方法创建100个单元测试。
希望我的回答可以帮到你! 最好的问候,米哈伊尔。
答案 1 :(得分:1)
私有和受保护的方法是被测代码的实现细节,不应进行测试。您的测试会告诉您代码应该做什么。测试私有方法和受保护方法开始进入“代码应该如何”执行它正在做的事情。
当您修改类以添加一些私有方法时,因为您发现了一些代码重用并且测试失败,您知道这是因为您更改了某些功能并需要修复该测试用例。如果您对私有方法和受保护方法进行了测试,那么现在您需要查看测试是否由于正当理由而失败,或者是您的重新分解。私有和受保护的方法通过类的公共接口测试覆盖,不需要自己的任何测试。
仅仅因为你“可以”做某事并不意味着你“应该”做某事。
当我测试时,我认为被测系统是黑盒子。我给它一些东西,我希望有一些事情发生。我不在乎里面发生了什么。所有重要的是给出了正确的输出。
复杂的内部函数是一种代码气味,也许我的班级做得太多了,可能还有另一个隐藏在里面的类。
答案 2 :(得分:0)
我认为私有/受保护方法的测试取决于它们的访问位置和方式,以及正在测试的内容。
如果我正在构建可重用的公共代码库,那么这些类中的私有和受保护方法将在库测试用例中进行测试。这些测试确保较低级别的代码有效,因此我可以对库有信心。
现在,当我编写一个访问该库的业务应用程序时,我不会为库对象编写测试,因为它们将在业务应用程序的测试中被模拟。库测试显示库工作,然后业务应用程序测试显示应用程序正常工作。
业务应用程序不会尝试测试库的私有/受保护方法,因为我认为是一个我不了解的黑盒代码(类似于外部库或Web服务)。但是,我确实在业务应用程序的测试套件中测试业务应用程序的私有和受保护方法,以确保方法/功能按照应有的方式运行。
作为一个例子,假设以下业务类(非常简短地传达思想,而不是函数):
<?php
class ACCOUNTS
{
protected GetEstimation()
{
...
return $CalculatedValue;
}
}
class CUSTOMER_ACCOUNT extends ACCOUNTS
{
protected GetEstimation()
{
$BaseEstimation = parent::GetEstimation();
...
return $NewCalculatedValue
}
}
class RESELLER_ACCOUNT extends ACCOUNTS
{
protected GetEstimation()
{
...
return $ResellerCalculatedValue; // Note: No call to parent
}
}
?>
在此示例中,将返回不同的值。使用了Protected函数,因此可以覆盖它,并且它不必依赖父类功能。在这个例子中,我想测试所有这些类在使用时返回正确的值。
基本的ACCOUNTS类应在根据类值进行计算后返回Estimation。通常,我只需设置值并测试返回值:
<?php
class ACCOUNTSTest extends PHPUnit_Framework_TestCase
{
protected $Accounts;
protected function setUp()
{
$this->Accounts = new ACCOUNTS();
}
public function testEstimationHome()
{
$this->Accounts->InternalValue1 = 1;
$this->Accounts->InternalValue2 = 10;
$this->Accounts->InternalValue3 = 100;
$this->assertEquals(523, $this->Accounts->GetEstimation(), 'Test Home Account with values 1, 10, 1000');
}
public function testEstimationHome2()
{
$this->Accounts->InternalValue1 = 5;
$this->Accounts->InternalValue2 = 2;
$this->Accounts->InternalValue3 = 10;
$this->assertEquals(253, $this->Accounts->GetEstimation(), 'Test Home Account with values 5, 2, 10');
}
protected function tearDown()
{
unset($this->Accounts);
}
}
?>
现在,这些测试将确保ACCOUNTS-&gt; GetEstimation()正常工作。然后我会测试CUSTOMER_ACCOUNT,并进行类似的测试以确保该类正确计算。
是的,如果基类发生了变化,那么我可能需要更新CUSTOMER_ACCOUNT中的测试,因为ACCOUNTS-&gt; GetEstimation()发生了变化,但我还要额外检查基类是否仍然正确返回。 / p>
或者,我可以更改此结构并使用依赖注入来提供某些信息(ACCOUNTS),以确保如果父估计始终为523,则此类返回正确的值。如果ACCOUNTS更改了返回的估计值,并且这个类没关系(可能这个类只是添加其他值),那么我将我的测试隔离开来,不用担心。
希望此更新有助于说明我的意思。