Unit testing 使用私有/受保护常量测试类

Unit testing 使用私有/受保护常量测试类,unit-testing,constants,access-modifiers,php-7.1,Unit Testing,Constants,Access Modifiers,Php 7.1,在测试类方法时,有时我需要将返回值与某个类中定义的某个常量进行比较 class FooBar { const RANDOM = 18; } .... // Somewhere in test... $this->assertEquals(FooBar::RANDOM, $mock->doSomething()); 现在,由于PHP 7.1可以使用visibility修饰符定义类常量,因此可以将其更改为: private const RANDOM = 18; 但是,这会使测

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

class FooBar
{
    const RANDOM = 18;
}
....
// Somewhere in test...
$this->assertEquals(FooBar::RANDOM, $mock->doSomething());
现在,由于PHP 7.1可以使用visibility修饰符定义类常量,因此可以将其更改为:

private const RANDOM = 18;
但是,这会使测试停止工作,因为现在我们正试图访问私有常量

现在我们有两个选择:

  • 将该常量声明为public
  • 在测试中使用反射。意味着测试变成:
  • $this->assertEquals(
    (新的ReflectionClass(FooBar::class))->getConstant('RANDOM'),
    $mock->doSomething()
    );

    第一种方法感觉非常错误,因为我们只是为了测试而不断公开,而不是因为类/层次结构/业务模型需要公开

    第二个也感觉不对劲,因为找不到这个用例 因此,任何搜索/替换/重构都会在这里失败


    所以我的问题是,第二个场景是否应该在不考虑重构会破坏测试的情况下使用?或者,甚至在一般情况下,也不应在主张中使用常量

    在测试中使用常数实际上是一种不好的做法

    您应该测试常量的文本值。
    $this->assertSame(18,$mock->doSomething())

    为什么?

    因为测试带给您的一个重要价值是,您会注意到代码更改的意外后果。因为常量是私有的,所以它的值永远不会在类之外使用。但是许多不同的事情可能取决于它的内部值

    现在想象一下,一位不熟悉代码库的初级开发人员负责更改常量的使用位置,并将其从18更改为16。他将去将常量的值从18更改为16,并对常量的使用位置进行粗略检查(不注意doSomething()方法).现在,在你的方法中,你绝对需要随机数为18,而不是16!但是如果你使用常数,他永远不会知道,因为当他将它从18改为16时,断言也会从18改为16。测试就会通过

    我的经验法则是:

    切勿使用从程序代码中提取的预期断言值 在可能的情况下,始终使用文字值