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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 21:35:16