测试私有/受保护常量的类

6

在测试类方法时,有时我需要将返回值与某个类中定义的常量进行比较。

class FooBar
{
    const RANDOM = 18;
}
....
// Somewhere in test...
$this->assertEquals(FooBar::RANDOM, $mock->doSomething());

从 PHP 7.1 开始,我们可以使用可见性修饰符定义类常量。因此,这段代码可以改为:

private const RANDOM = 18;

然而,这样做会导致测试无法工作,因为现在我们试图访问私有常量。
因此,现在我们有两个选择:
1.将常量声明为public。
2.在测试中使用反射。意味着测试变成了: $this->assertEquals( (new ReflectionClass(FooBar::class))->getConstant('RANDOM'), $mock->doSomething() );
第一种方法感觉非常不对,因为我们只是为了测试而将常量设为public,而不是因为类/层次结构/业务模型需要它成为public。
第二种方法也不太对,因为任何IDE都找不到这种用例,所以任何搜索/替换/重构都会失败。
因此,我的问题是,应该使用第二种方案而不关心重构会破坏测试吗?或者甚至应该避免在断言中使用常量?
1个回答

5
在我的看法中,测试中使用常量实际上是一种不良的做法。
你应该测试该常量的字面值。例如:$this->assertSame(18, $mock->doSomething())
为什么呢?因为测试带给你的最重要的价值之一就是发现代码更改的意外后果。由于常量是私有的,其值在类外部从未被使用过。但内部可能有许多不同的东西依赖于它的值。
现在想象一个不熟悉代码库的初级开发人员正在修改其中一个使用了该常量的地方,并将其从18更改为16。他会更改常量的值从而使得对使用该常量的位置进行简单检查(没有注意到doSomething()方法)。 现在,在您的方法中,您绝对需要随机数为18,而不是16!但是如果您使用了常量,他永远不会知道,因为当他将其从18更改为16时,assertion也将从18更改为16。然后测试将通过。
对我而言,原则是:从应用程序代码中获取断言的期望值时,永远不要使用常量。尽可能使用字面值进行测试。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接