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

Laravel9中用Mockery模拟同一类内静态方法的问题与解决

Laravel单元测试:模拟静态方法调用的问题与解决

被测代码

我需要测试Laravel项目中Foo类的testMethod()方法,类代码如下:

class Foo extends Model
{
    public static function staticMethod($arg)
    {
         return 'from staticMethod';
    }
    public function testMethod($arg)
    {
         $result = self::staticMethod($arg);
         return $result;
    }
}

测试过程与问题

Edit 1:初次尝试的问题

按照@Charlie的建议,我编写了如下测试代码:

$mock = \Mockery::mock(Foo::class);
$mock->shouldReceive('staticMethod')
   ->once()
   ->andReturn('mocked return value');

$this->app->instance(Foo::class, $mock);

$mockedFoo = app(Foo::class);

$result = $mockedFoo->testMethod('test argument');

测试中发现两种调用方式结果不一致:

// 返回'mocked return value'
$mockedFoo->staticMethod('test');

// 返回原方法值
Foo::staticMethod('test');

由于被测代码里是通过Foo::staticMethod()(即self::staticMethod())调用,并非实例调用,因此模拟未生效。同时测试抛出错误:

Mockery\Exception\BadMethodCallException: Received Mockery_2_App_Models_Foo::testMethod(), but no expectations were specified

我希望testMethod()按原逻辑执行,不需要设置模拟返回值,于是尝试用makePartial():

$mock = \Mockery::mock('overload:'.Foo::class)->makePartial();

但此时静态方法的模拟依然未生效,还是会调用原方法。

Edit 2:修改代码后的成功解决

按照@matiaslauriti的建议,我修改了测试代码(未使用overload:,因为使用后即使加makePartial()也会报testMethod() does not exist on this mock object错误):

$mock = \Mockery::mock(Foo::class)->makePartial();
$mock->shouldReceive('staticMethod')
   ->once()
   ->andReturn('mocked return value');

$this->app->instance(Foo::class, $mock);

$mockedFoo = app(Foo::class);

$result = $mockedFoo->testMethod('test argument');

同时修改了Foo类的testMethod(),将self::改为static:::

public function testMethod($arg)
{
     return static::staticMethod($arg);
}

修改后测试运行成功,静态方法的模拟生效了!

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 04:35:05