Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 我应该测试私有/受保护的方法吗?为什么?_Unit Testing_Testing_Junit_Phpunit - Fatal编程技术网

Unit testing 我应该测试私有/受保护的方法吗?为什么?

Unit testing 我应该测试私有/受保护的方法吗?为什么?,unit-testing,testing,junit,phpunit,Unit Testing,Testing,Junit,Phpunit,我对私有/受保护方法的测试有疑问。这是一个针对任何平台的单元测试的一般问题。但我要告诉你们的是,我正在使用phpunit平台对php进行单元测试 我们应该测试私有/受保护的方法吗?对此公认的答案是,我们通常不应该这样做。 根据这一回答: 通常,您不直接测试或模拟私有和受保护的方法 您要测试的是类的公共API。其他一切都是一个问题 类的实现细节,并在更改测试时不显示“中断”测试 但与此同时,许多问题中的其他答案提供了一种测试方法(我假设这些答案意味着我们应该测试私有/受保护的方法,因为他们没有说我

我对私有/受保护方法的测试有疑问。这是一个针对任何平台的单元测试的一般问题。但我要告诉你们的是,我正在使用phpunit平台对php进行单元测试

我们应该测试私有/受保护的方法吗?对此公认的答案是,我们通常不应该这样做。 根据这一回答:

通常,您不直接测试或模拟私有和受保护的方法

您要测试的是类的公共API。其他一切都是一个问题 类的实现细节,并在更改测试时不显示“中断”测试

但与此同时,许多问题中的其他答案提供了一种测试方法(我假设这些答案意味着我们应该测试私有/受保护的方法,因为他们没有说我们应该或不应该测试它们)


请给我解释一下原因。谢谢。

至于我,这取决于私有/受保护成员的复杂性

例如,您有具有复杂计算的私有方法Func1()和Func2(),或具有许多输入参数的算法。您有一个使用这两种方法的公共API。在某些数据上,Func1()被破坏并返回不正确的数据,但在Func2()处理过程中,该数据以某种方式转换为正确的结果(由于其他问题)。公共API方法的总结果将是正确的-这意味着您的Func1和Func2不正确,但您的API在某种程度上是正确的。你测试了一下就没事了

现在,您将代码交给了某人,他/她创建了Func3()和另一个使用Func1()和Func3()的公共API方法,但该API方法的单元测试失败。他/她将花费多少时间来查明原因在功能1中?当Func1修复后,您将进行上一次测试,Func2失败。。。那完全不好

因此,如果私有/受保护的方法很复杂(很多代码或使用不明显的算法)且可重用,那么您应该如何测试它们。当然,您不需要为返回a+b或编写调试日志记录的私有方法创建100个单元测试

希望我的回答能帮助你!
致以最诚挚的问候,Mikhail。

我相信私有/受保护方法的测试取决于访问它们的位置/方式以及测试内容

如果我正在构建一个公共代码的可重用库,那么这些类中的私有和受保护方法将在库测试用例中进行测试。这些测试确保了较低级别的代码能够正常工作,因此我可以信任库

现在,当我编写访问此库的业务应用程序时,我不会为库对象编写测试,因为它们将在业务应用程序的测试中被模拟。库测试显示库工作正常,然后业务应用程序测试显示应用程序工作正常

业务应用程序不尝试测试库的私有/保护方法,因为我认为这是一个我不知道的黑盒(类似于外部库或Web服务)。但是,我会在业务应用程序的测试套件中测试业务应用程序的私有和受保护方法,以确保方法/功能按其应有的方式运行

作为示例,假设以下业务类(非常简短,用于传达思想,而不是功能):


在本例中,将返回不同的值。使用受保护的函数是为了可以重写它,并且它不必依赖父类功能。在本例中,我确实希望测试所有这些类在使用时是否返回正确的值

基本ACCOUNTS类应在根据类值进行计算后返回估计值。通常,我只需设置值并测试返回:

<?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_帐户,并进行类似的测试以确保该类计算正确

是的,如果基类发生更改,那么我可能需要更新CUSTOMER_帐户中的测试,因为ACCOUNTS->GetEstimation()发生了更改,但是我还需要额外检查基类是否仍然正确返回

或者,我可以更改此结构并使用依赖项注入来提供某些信息(帐户),以确保如果父估计值始终为523,则该类返回正确的值。如果ACCOUNTS更改了返回的估计值,并且这与这个类无关(可能这个类只是简单地添加了额外的值),那么我隔离了我的测试,不需要担心


希望此更新有助于说明我所说的内容。

私有和受保护方法是测试代码的实现细节,不应进行测试。测试告诉您代码应该做什么。测试私有和受保护的方法开始进入“如何”您的代码应该做什么

当您修改类以添加一些私有方法时,因为您发现了一些代码重用,并且测试失败,您知道这是因为您更改了一些功能并需要修复该测试用例。如果您有针对私有和受保护方法的测试,并且您现在也做了同样的事情,那么您需要查看测试是否由于有效的原因而失败,或者是由于重新分解。私有和受保护的方法通过类的公共接口的测试来覆盖,不需要自己的任何测试

仅仅因为你“能”做某事并不意味着你“应该”做某事

当我测试时,我认为被测试的系统是一个黑盒子。我给了它一些东西,我期待着一些事情发生。我不在乎里面发生了什么。重要的是给出正确的输出

复杂的内部功能
<?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);
    }
}
?>