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

Mockery中mock()->makePartial()链式调用shouldReceive报错原因

问题根因

这不是makePartial()方法的问题,是对Mockery链式调用的返回值类型认知错误导致的:

  • Mockery::mock()、makePartial()这类初始化mock对象本身的方法,返回值确实是生成的模拟对象实例,可以链式调用同类初始化方法。
  • shouldReceive()、with()、andReturn()这类配置方法调用期望的方法,返回值不是mock对象,而是Mockery\Expectation类的实例——这个类的作用是定义mock方法的匹配规则、返回值、调用次数约束,本身不具备你模拟的业务类的方法。

两种写法的差异本质是变量存储的值完全不同:

  • 分写的逻辑:第一行把makePartial()返回的mock实例赋值给$mock,第二行调用$mock->shouldReceive(123)时,返回的Expectation对象没有被赋值给任何变量,$mock里存的始终是合法的mock实例,后续调用setTime等业务方法自然正常。
  • 错误链式写法的逻辑:PHP链式赋值取最后一个方法的返回值,$mock最终存的是shouldReceive()返回的Expectation实例,你后续把这个Expectation对象当初始化好的mock用,调用setTime()方法时,Expectation类里根本不存在这个方法,就会抛出你看到的错误:

TypeError: call_user_func_array(): Argument #1 ($callback) must be a valid callback, class Mockery\Expectation does not have a method "setTime"

正确写法

推荐写法(分写,可读性最高,不容易出错)

$mock = Mockery::mock()->makePartial();
$mock->shouldReceive(123);
// 后续正常调用mock的业务方法即可
$mock->setTime(time());

链式写法(如果必须写在同一组调用链里)

配置完所有期望规则后,调用Expectation类的getMock()方法拿回真正的mock实例再赋值:

$mock = Mockery::mock()->makePartial()
  ->shouldReceive(123)
  ->andReturn('mock_result') // 可继续链式配置期望:入参规则、返回值、调用次数等
  ->getMock();
// 此时$mock是合法的模拟对象,可正常调用业务方法
$mock->setTime(time());

内容的提问来源于stack exchange,提问作者Artem Ivanov

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.30 08:46:34