PHPUnit中如何Stub/Mock函数返回值?Stub静态方法为何无效?
PHPUnit Stub静态方法未生效的问题与解决
问题描述
按照PHPUnit官方文档尝试Stub简单函数时未生效,现有类代码如下:
<?php declare(strict_types=1); class A { public static function func() { $helperData = A::helper(); return $helperData + 1; } public static function helper() { return 5; } }
测试类代码:
<?php declare(strict_types=1); use PHPUnit\Framework\TestCase; final class ATest extends TestCase { public function testFunc(): void { $stub = $this->createStub(A::class); $stub->method('helper') ->willReturn(2); $result = A::func(); $this->assertEquals(3, $result); // actual result is 6 not 3--why? } }
Stub后的helper方法未按指定返回2,调用A::func()实际得到6而非预期3。
问题原因
createStub创建的是类的实例对象,但A::func()内部调用的是静态方法A::helper(),实例的Stub设置仅对该实例的方法生效,完全不会影响类本身的静态方法执行。- 静态方法属于类本身的属性,而非实例,所以对实例的Stub配置无法作用到静态方法上。
解决方法
方法一:重构代码(推荐,符合面向对象设计原则)
将静态方法改为实例方法,让类的行为依赖于实例,这样就能正常使用Stub:
修改类A:
<?php declare(strict_types=1); class A { public function func() { $helperData = $this->helper(); return $helperData + 1; } public function helper() { return 5; } }
修改测试代码:
<?php declare(strict_types=1); use PHPUnit\Framework\TestCase; final class ATest extends TestCase { public function testFunc(): void { $stub = $this->createStub(A::class); $stub->method('helper') ->willReturn(2); $result = $stub->func(); $this->assertEquals(3, $result); } }
方法二:Mock静态方法(不推荐,耦合性高)
如果无法修改原代码,可以使用PHPUnit的MockStatic功能(PHPUnit 9.5及以上版本支持)来Mock静态方法:
修改测试代码:
<?php declare(strict_types=1); use PHPUnit\Framework\TestCase; use PHPUnit\Framework\MockObject\MockStatic; final class ATest extends TestCase { public function testFunc(): void { /** @var MockStatic $mockStatic */ $mockStatic = $this->createMock(A::class); $mockStatic::staticExpects($this->once()) ->method('helper') ->willReturn(2); $result = A::func(); $this->assertEquals(3, $result); } }
注意:这种方式会全局Mock类的静态方法,测试结束后PHPUnit会自动还原,但会增加测试与代码的耦合度,仅作为无法重构时的备选方案。
内容的提问来源于stack exchange,提问作者yalpsid eman
相关产品推荐
相关产品推荐

