Laravel中Mockery部分模拟仍接收全部方法调用问题排查
问题原因
你出现这个报错的核心原因是:你是对接口MyServiceInterface做的部分模拟,而不是对实现类myService做的部分模拟。
接口本身只有方法签名,没有实际的方法实现逻辑,Mockery的部分模拟没有可以 fallback 的原有执行逻辑,所以所有被调用的方法都必须预先声明调用预期,否则就会抛出你遇到的BadMethodCallException。
解决方案
你可以选以下任意一种方案处理:
方案1:改为对实现类做部分模拟(推荐)
将部分模拟的目标从接口换成你的服务实现类,同时将模拟实例绑定到服务容器的接口标识上,这样未声明预期的cleanString方法就会自动走原有实现:
$this->mock = $this->partialMock(\App\Services\myService::class, function (MockInterface $mock) use ($testData) { $mock->shouldReceive('method1')->andReturn(null); $mock->shouldReceive('method2')->andReturn($testData[0]); $mock->shouldReceive('method3')->andReturn(count($testData) - 1); $mock->shouldReceive('method4')->andReturn(array_slice($testData, 1), false); }); // 绑定模拟实例到接口,保证依赖注入时能拿到模拟对象 $this->app->bind(MyServiceInterface::class, fn() => $this->mock);
方案2:给cleanString补充调用预期
如果你必须保留对接口的模拟,可以直接给cleanString方法加预期,调用真实服务的对应逻辑:
$this->mock = $this->partialMock(MyServiceInterface::class, function (MockInterface $mock) use ($testData) { // 原有其他方法的预期保留 $mock->shouldReceive('method1')->andReturn(null); $mock->shouldReceive('method2')->andReturn($testData[0]); $mock->shouldReceive('method3')->andReturn(count($testData) - 1); $mock->shouldReceive('method4')->andReturn(array_slice($testData, 1), false); // 新增cleanString的预期,走真实实现逻辑 $mock->shouldReceive('cleanString')->andReturnUsing(fn($string) => (new \App\Services\myService)->cleanString($string)); });
内容的提问来源于stack exchange,提问作者qotsa42
相关产品推荐
相关产品推荐

