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

2022-08-30 14:28:48

假设我有一个具有私有属性和关联的公共 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) “杰拉德”

字符串(6) “杰拉德”

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

或者我应该在测试中做一些其他事情来捕获这样的问题,而无需尝试访问被测对象的私有状态?


答案 1

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

查看 https://github.com/sebastianbergmann/phpunit/blob/3.7/PHPUnit/Framework/Assert.php#L490


答案 2

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

您通常不想这样做

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

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

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


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

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


如果你真的想这样做,PHP反射API中有功能,但我无法编造一个我觉得这很理想的例子。setAccessible

查找未使用的属性以捕获错误/问题,如下所示:

PHP 混乱检测器作为未使用的隐私字段规则

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

这将为您生成两个警告,因为永远不会访问变量


推荐