PHPUnit单元测试:使用真实类常量还是测试类新增常量?
优先使用真实类的常量,别在测试里复制!
这是个很实际的单元测试问题,直接给你结论:绝大多数情况下,你应该直接引用原类LoremIpsum里的VALUE常量,而不是在测试类里复制一个相同值的常量。下面给你讲清楚原因,以及特殊情况的处理方式:
为什么复制常量到测试类是坏主意?
- 维护噩梦:哪天原类的
VALUE从'123'改成'456',你得同步修改测试类里的常量,不然测试直接失败。多一个地方要改,就多一分出错的可能。 - 测试逻辑跑偏:单元测的核心是验证真实业务代码的逻辑。如果测试用自己定义的常量,相当于你在测“测试类的常量是否符合预期”,而不是原方法用真实常量跑出来的结果对不对——这完全偏离了测试的初衷。
正确的打开方式:直接用真实常量
在测试方法里直接调用\Namespace\LoremIpsum::VALUE,让测试和真实代码绑定,示例代码如下:
namespace Namespace; class LoremIpsumTest { public function testMethodThatUsesConstant() { $loremInstance = new LoremIpsum(); $methodResult = $loremInstance->MethodThatUsesConstant(); // 用真实常量做断言,确保逻辑和原代码一致 $this->assertEquals(LoremIpsum::VALUE, $methodResult); } }
例外场景:需要测试不同常量值的情况
如果你的测试需要验证方法在不同常量值下的行为(比如边界测试、错误分支测试),这时候可以通过两种方式处理:
方法1:重构原类,用依赖注入
如果原类的代码允许修改,最好把常量改成可注入的依赖,这样测试时能灵活传不同值,也让代码更灵活:
// 重构后的原类 class LoremIpsum { private $value; // 把常量作为默认参数,兼容原有调用方式 public function __construct(string $value = self::VALUE) { $this->value = $value; } public function MethodThatUsesConstant() { // 用$this->value替代self::VALUE return $this->value; } const VALUE = '123'; } // 测试类 class LoremIpsumTest { public function testMethodWithDefaultConstantValue() { $lorem = new LoremIpsum(); $this->assertEquals('123', $lorem->MethodThatUsesConstant()); } public function testMethodWithCustomValue() { // 测试自定义值的场景 $lorem = new LoremIpsum('456'); $this->assertEquals('456', $lorem->MethodThatUsesConstant()); } }
方法2:用子类覆盖常量(仅当无法重构时)
如果原类不能改,PHP里可以通过创建测试子类来覆盖常量,但要注意限制:
// 测试用的子类,覆盖原常量 class MockLoremIpsum extends LoremIpsum { const VALUE = '456'; } class LoremIpsumTest { public function testMethodWithMockedConstantValue() { $lorem = new MockLoremIpsum(); $result = $lorem->MethodThatUsesConstant(); $this->assertEquals('456', $result); } }
⚠️ 注意:这种方法只在原方法用static::VALUE(而不是self::VALUE)时生效,因为self会绑定到原类,而static是后期静态绑定,会用子类的常量。如果原方法用的是self::VALUE,这个技巧就没用了,还是优先考虑重构。
内容的提问来源于stack exchange,提问作者Anonim Wd
相关产品推荐
相关产品推荐

