我相信私有/受保护方法的测试取决于访问它们的位置/方式以及正在测试的内容。
如果我正在构建一个可重用的通用代码库,那么这些类中的私有和受保护方法将在库测试用例中进行测试。这些测试确保较低级别的代码可以正常工作,因此我可以对库有信心。
现在,当我编写访问该库的业务应用程序时,我不会为库对象编写测试,因为它们将在业务应用程序的测试中被模拟。库测试显示库工作,然后业务应用程序测试显示应用程序工作。
业务应用程序不会尝试测试库的私有/受保护方法,因为我认为这是一个我不知道的黑盒代码(类似于外部库或 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
}
}
?>
在此示例中,将返回不同的值。使用了受保护的函数,因此它可以被覆盖,并且它不必依赖父类的功能。在此示例中,我确实想测试所有这些类在使用时返回正确的值。
基本 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->GetEstimation() 正常工作。然后我会测试 CUSTOMER_ACCOUNT,并进行类似的测试以确保该类计算正确。
是的,如果基类发生变化,那么我可能需要更新 CUSTOMER_ACCOUNT 中的测试,因为 ACCOUNTS->GetEstimation() 发生了变化,但我还要额外检查基类是否仍然正确返回。
或者,我可以更改此结构并使用依赖注入来提供某些信息(帐户),以确保如果父估计始终为 523,则此类返回正确的值。如果 ACCOUNTS 更改了返回的估计值,并且对这个类无关紧要(也许这个类只是添加附加值),那么我隔离我的测试并且不需要担心。
希望此更新有助于说明我在说什么。