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

如何在PHPUnit中不使用依赖注入实现Mock测试?

问题解答

为啥你的Mock没生效,测试还通过了?

你的Check::checkAdd方法里是直接在内部new了真实的Calculator实例,和你在测试里创建的Mock对象完全是两个独立的东西。真实的Calculator::add返回5+2=7,和你计算的sum值相等,所以assertTrue($result)自然会通过。


不使用依赖注入,怎么让测试用上Mock值?

对于硬编码在方法里的new Calculator(),要替换成Mock对象,有两种实用方案:

方案1:用PHPUnit Mock + 类别名替换

先创建Calculator的Mock,然后通过class_alias让Calculator这个类名指向你的Mock类,这样当Check方法里执行new Calculator()时,实际创建的是Mock实例。

修改后的测试代码:

public function testValidateAdd()
{
    // 创建Calculator的Mock,指定只mock add方法
    $calculatorMock = $this->getMockBuilder(Calculator::class)
        ->onlyMethods(['add'])
        ->getMock();
    // 设置Mock的add方法返回3
    $calculatorMock->method('add')->willReturn(3);

    // 让系统把Calculator类名指向我们的Mock类
    class_alias(get_class($calculatorMock), 'Calculator');

    $check = new Check();
    $result = $check->checkAdd(5, 2);
    // 此时sum是7,Mock返回3,$result为false,断言会失败(符合你的预期)
    $this->assertTrue($result);
}

注意:这种方式会影响整个测试进程中的Calculator类,建议在测试结束后用class_alias重新指向真实的Calculator类,或者在tearDown方法里清理。

方案2:用匿名类临时替换(更轻量)

创建一个继承自Calculator的匿名类,重写add方法返回你想要的值,再通过类别名替换,效果和Mock一致:

public function testValidateAdd()
{
    // 创建匿名类重写add方法
    $mockCalculator = new class extends Calculator {
        public function add($num1, $num2)
        {
            return 3;
        }
    };
    // 替换Calculator类名指向匿名类
    class_alias(get_class($mockCalculator), 'Calculator');

    $check = new Check();
    $result = $check->checkAdd(5, 2);
    $this->assertTrue($result); // 断言失败,符合预期
}

题外话:为啥推荐用依赖注入?

你现在遇到的测试困难,本质是代码紧耦合导致的——Check直接绑定了Calculator的具体实现,而不是依赖抽象。依赖注入(构造注入、方法注入)是解决这类问题的标准方案,比如修改Check类:

class Check
{
    private $calculator;

    // 构造注入Calculator实例
    public function __construct(Calculator $calculator)
    {
        $this->calculator = $calculator;
    }

    public function checkAdd($num1, $num2)
    {
        $sum = $num1 + $num2;
        $res = $this->calculator->add($num1, $num2);
        return $sum == $res;
    }
}

这样你的原测试代码就能直接生效,而且代码耦合度更低,后续扩展或替换Calculator实现也更方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.25 06:04:53