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
相关产品推荐
相关产品推荐

