PHPUnit:对非公共变量进行断言



假设我有一个具有私有属性和关联的公共getter和setter的类。我想用PHPUnit测试在使用了setter之后属性是否得到了正确的值,或者getter是否返回了正确的属性。

当然,我可以通过使用getter来测试setter,以查看对象是否存储了正确的值,反之亦然,以测试getter。然而,这并不能保证私有财产就是正在设置的财产。

假设我上了下面的课。我创建了一个属性getter和setter。但我在属性名称中打了一个错别字,所以getter和setter实际上并没有操纵它们要操纵的属性

class SomeClass
{
    private 
        $mane = NULL; // Was supposed to be $name but got fat-fingered!
    public function getName ()
    {
        return ($this -> name);
    }
    public function setName ($newName)
    {
        $this -> name = $newName;
        return ($this);
    }
}

如果我运行以下测试

public function testSetName ()
{
    $this -> object -> setName ('Gerald');
    $this -> assertTrue ($this -> object -> getName () == 'Gerald');
}

我会得到通行证的。然而,实际上发生了一些我不想发生的非常糟糕的事情。当调用setName()时,它实际上在类中创建了一个新属性,其名称为我认为我的私有属性的名称,只有setter创建的属性是公共的!我可以用以下代码来证明这一点:

$a  = new SomeClass;
$a -> setName('gerald');
var_dump ($a -> getName ());
var_dump ($a -> name);

它将输出:

串(6)";gerald";

串(6)";gerald";

有没有什么方法可以从PHPUnit访问私有属性,这样我就可以编写测试,确保我认为正在获取和设置的属性实际上正在获取和设定?

或者,在测试中,我是否应该做一些其他事情来发现这样的问题,而不试图访问被测试对象的私有状态?

您也可以使用Assert::assertAttributeEquals('value', 'propertyName', $object)

请参阅https://github.com/sebastianbergmann/phpunit/blob/3.7/PHPUnit/Framework/Assert.php#L490

对于测试属性,我会提出与讨论测试私有方法时相同的论点。

You usually don't want to do this

这是关于测试可观察的行为。

如果重命名所有属性或决定将它们存储到数组中,则根本不需要调整测试。您希望您的测试告诉您一切仍然有效!当您需要更改测试以确保一切正常时,您将失去所有好处,因为更改测试也可能出错。

所以,总而言之,您将失去测试套件的价值!


仅仅测试get/set组合就足够了,但通常并不是每个setter都应该有getter,仅仅创建它们进行测试并不是一件好事。

通常,你设置一些东西,然后告诉方法DO(行为)一些东西。为此进行测试(类做应该做的事情)是测试的最佳选择,并且应该使测试属性变得多余。


如果你真的想这样做,在PHP反射API中有setAccessible功能,但我不能编一个例子来找到这个理想的

查找未使用的属性以捕获像以下这样的错误/问题:

PHP Mess检测器作为UnusedPrivateField Rule

class Something
{
    private static $FOO = 2; // Unused
    private $i = 5; // Unused
    private $j = 6;
    public function addOne()
    {
        return $this->j++;
    }
}

这将为您生成两个警告,因为变量从未被访问

我只想指出一件事。让我们暂时忘记私有字段,把注意力集中在您班的客户关心的内容上。您的类公开了一个契约,在本例中是更改和检索名称的能力(通过getter和setter)。预期功能很简单:

  • 当我用setName将名称设置为"Gerald"时,我希望在调用getName时得到"Gerald"

仅此而已。客户不会(好吧,不应该!)关心内部实现。无论您是使用私有字段名、哈希集还是通过动态生成的代码调用web服务,对客户端来说都无关紧要。从用户的角度来看,您当前遇到的错误根本不是错误。

PHPUnit是否允许您测试私有变量——我不知道。但从单元测试的角度来看,您不应该这样做。

编辑(回应评论):

我理解您对内部状态可能暴露的担忧,但我不认为单元测试是处理这一问题的正确工具。你可以想出很多可能的场景,一些可能会做其他没有计划的事情。单元测试决不能包治百病,不应该这样使用。

我同意其他人的观点,即通常情况下,您希望避免在测试中访问私有属性,但在需要的情况下,可以使用反射来读取和写入属性。

相关内容

  • 没有找到相关文章

最新更新