You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在PHPUnit/Mockery中Mock或修改类常量SCHEMA_REPO的值?

如何在PHPUnit/Mockery中替换遗留类的常量值

为什么Mockery的Constant Maps没生效

Mockery的Constant Maps功能仅用于模拟被Mock类所依赖的外部常量(比如全局常量、其他类的常量),无法修改被Mock类自身已定义的常量。你创建的Mock实例会继承原类的常量定义,所以输出的仍是原有值。

可行的解决方法

方法1:测试目录下创建同名类覆盖(推荐,无扩展依赖)

如果项目遵循PSR-4自动加载规则,可在测试目录下创建与原类完全一致的命名空间和类文件,重写目标常量为测试值:

  1. 原类示例(src/Repos/LegacyRepo.php):
namespace App\Repos;

class LegacyRepo {
    const SCHEMA_REPO = ['MailNotice' => MailNotice::class];
    
    public function getSchemas() {
        return self::SCHEMA_REPO;
    }
}
  1. 测试目录下创建同名类(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;
    }
}
  1. 运行测试时,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:

  1. 修改原类,新增静态方法包裹常量:
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();
    }
}
  1. 测试时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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 03:32:48