如何在PHPUnit/Mockery中Mock或修改类常量SCHEMA_REPO的值?
如何在PHPUnit/Mockery中替换遗留类的常量值
为什么Mockery的Constant Maps没生效
Mockery的Constant Maps功能仅用于模拟被Mock类所依赖的外部常量(比如全局常量、其他类的常量),无法修改被Mock类自身已定义的常量。你创建的Mock实例会继承原类的常量定义,所以输出的仍是原有值。
可行的解决方法
方法1:测试目录下创建同名类覆盖(推荐,无扩展依赖)
如果项目遵循PSR-4自动加载规则,可在测试目录下创建与原类完全一致的命名空间和类文件,重写目标常量为测试值:
- 原类示例(
src/Repos/LegacyRepo.php):
namespace App\Repos; class LegacyRepo { const SCHEMA_REPO = ['MailNotice' => MailNotice::class]; public function getSchemas() { return self::SCHEMA_REPO; } }
- 测试目录下创建同名类(
tests/Unit/App/Repos/LegacyRepo.php):
namespace App\Repos; class LegacyRepo { const SCHEMA_REPO = ['TestNoticeA'=>'TestNoticeA','TestNoticeB'=>'TestNoticeB']; // 复制原类的方法逻辑,保证测试行为与原类一致 public function getSchemas() { return self::SCHEMA_REPO; } }
- 运行测试时,PHPUnit的自动加载器会优先加载测试目录下的类,从而覆盖原类的常量定义。
方法2:使用Reflection扩展修改常量(hack手段,谨慎使用)
PHP的Reflection API可通过修改类的内部常量存储实现替换(依赖PHP内部实现,版本兼容性需注意):
use App\Repos\LegacyRepo; use ReflectionClass; $reflection = new ReflectionClass(LegacyRepo::class); $constants = $reflection->getConstants(); $constants['SCHEMA_REPO'] = ['TestNoticeA'=>'TestNoticeA','TestNoticeB'=>'TestNoticeB']; // 调整反射属性权限并修改常量数组 $reflectionConstants = $reflection->getProperty('constants'); $reflectionConstants->setAccessible(true); $reflectionConstants->setValue(null, $constants); // 验证修改结果 var_dump(LegacyRepo::SCHEMA_REPO); // 输出测试值
方法3:最小侵入式重构(折中方案)
若允许对遗留类做极小修改,可用静态方法包裹常量访问,方便测试时Mock:
- 修改原类,新增静态方法包裹常量:
namespace App\Repos; class LegacyRepo { const SCHEMA_REPO = ['MailNotice' => MailNotice::class]; public static function getSchemaRepo() { return self::SCHEMA_REPO; } // 原有方法改为调用静态方法 public function getSchemas() { return self::getSchemaRepo(); } }
- 测试时Mock静态方法:
use Mockery; use App\Repos\LegacyRepo; Mockery::mock('overload:' . LegacyRepo::class) ->shouldReceive('getSchemaRepo') ->andReturn(['TestNoticeA'=>'TestNoticeA','TestNoticeB'=>'TestNoticeB']); $repo = new LegacyRepo(); var_dump($repo->getSchemas()); // 输出测试值
内容的提问来源于stack exchange,提问作者HerbertRedford
相关产品推荐
相关产品推荐

