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

Laravel测试用例使用Mockery时抛出getAttribute未设置预期异常

解决Mockery BadMethodCallException:getAttribute()调用未设置预期

当测试中Mock了Affiliate模型,但业务代码里通过属性访问(如$affiliate->commission_rate)触发了Laravel底层的getAttribute()方法,而Mock未预设该调用时,就会抛出这个异常。以下是几种可行的解决方式:

1. 优先使用模型工厂创建真实实例

如果测试场景允许,放弃Mock模型,改用Laravel模型工厂生成真实的Affiliate实例,这样属性访问的原生逻辑会正常运行:

$affiliate = Affiliate::factory()->create([
    'commission_rate' => 0.1,
    'user_id' => 1,
    // 填充测试所需的其他属性
]);

2. 为Mock预设getAttribute()的调用预期

若必须Mock模型,需明确为getAttribute()设置返回规则:

方式一:指定单个属性的返回值

针对业务代码中实际访问的属性,逐个设置预期:

$affiliateMock = Mockery::mock(Affiliate::class);
// 预设commission_rate属性的返回值
$affiliateMock->shouldReceive('getAttribute')
    ->with('commission_rate')
    ->andReturn(0.1);
// 若还有其他属性被访问,继续添加对应预期
$affiliateMock->shouldReceive('getAttribute')
    ->with('user_id')
    ->andReturn(1);

方式二:允许所有getAttribute()调用

如果不想逐个指定属性,可让Mock接受任意getAttribute()调用,返回默认值或自定义映射:

$affiliateMock = Mockery::mock(Affiliate::class);
// 所有属性访问返回null
$affiliateMock->shouldReceive('getAttribute')
    ->withAnyArgs()
    ->andReturnNull();

// 或者根据属性名返回对应值
$affiliateMock->shouldReceive('getAttribute')
    ->andReturnUsing(function ($key) {
        $mockAttributes = [
            'commission_rate' => 0.1,
            'user_id' => 1
        ];
        return $mockAttributes[$key] ?? null;
    });

3. 使用部分Mock(makePartial())

如果只需Mock模型的特定业务方法,保留getAttribute()等原生方法的功能,可创建部分Mock:

$affiliateMock = Mockery::mock(Affiliate::class)->makePartial();
// 仅Mock需要自定义的方法,比如calculateCommission
$affiliateMock->shouldReceive('calculateCommission')
    ->andReturn(10);

4. 检查业务代码的属性访问逻辑

确认OrderService或AffiliateService中是否存在未被测试覆盖的属性访问,比如遗漏了某个属性的Mock预期,补全对应的预设即可。

内容的提问来源于stack exchange,提问作者Wasim Rasheed

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 16:45:10