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

