Mockery是否克隆__get方法?Laravel模型Mock异常排查
问题解答
核心原因
Mockery 在默认情况下会继承被模拟类的所有公共方法,包括魔术方法 __get。你的 User 类中定义的 __get 是公共方法,所以生成的 Mock 对象会完整继承这个方法的逻辑。
当你访问 $user->abasdasd 这个不存在的属性时,PHP 会自动触发 __get 魔术方法,而该方法内部调用了 getAttribute()。由于你没有给 Mock 对象的 getAttribute() 方法设置任何调用预期(比如返回值、调用次数等),Mockery 就会抛出 BadMethodCallException 报错。
验证与解决方式
验证逻辑
你可以通过打印 Mock 对象的类结构来确认继承关系:
$user = Mockery::mock(User::class); var_dump(get_class_methods($user));
输出结果中会包含 __get 方法,证明它确实被 Mock 对象继承。
解决方法
根据测试需求,有几种处理方式:
- 设置
getAttribute的调用预期:如果需要让该方法返回特定值,直接配置即可:$user = Mockery::mock(User::class); $user->shouldReceive('getAttribute')->with('abasdasd')->andReturn(null); echo $user->abasdasd; // 不会触发报错 - Mock
__get方法:直接覆盖魔术方法的行为:$user = Mockery::mock(User::class); $user->shouldReceive('__get')->with('abasdasd')->andReturn(null); echo $user->abasdasd; // 不会触发报错 - 使用部分模拟(Partial Mock):如果需要保留原类的部分逻辑,同时 Mock 指定方法,可以用
makePartial():$user = Mockery::mock(User::class)->makePartial(); // 此时__get会执行原类逻辑,若需Mock其他方法仍需单独配置
内容的提问来源于stack exchange,提问作者Adam
相关产品推荐
相关产品推荐

