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

PHPUnit问题:无法Mock类内部的new Class实例

问题原因及解决方法

核心问题就是你在someClass的run方法里直接用new AnotherClass($params)硬编码创建实例,Yii的依赖注入容器完全管不到这种写法——容器只能接管通过容器获取实例的场景,比如构造注入、属性注入或者\Yii::$container->get()调用,直接new出来的实例和你注册到容器的Mock没有任何关系。

解决方案

方案一:用构造函数注入重构someClass(推荐)

修改someClass的代码,把AnotherClass的实例通过构造函数传入,彻底解耦依赖:

class someClass
{
    private $anotherClass;

    // 构造函数注入AnotherClass实例
    public function __construct(AnotherClass $anotherClass)
    {
        $this->anotherClass = $anotherClass;
    }

    public function run()
    {
        // 直接使用注入的实例,不再手动new
        $this->anotherClass->myMethod($data);
        // more code here ... 
    }
}

测试时直接把Mock传给someClass的构造函数就行,不需要再操作Yii容器:

$anotherClassMock = $this->getMockBuilder(AnotherClass::class)
    ->onlyMethods(['myMethod'])
    ->setConstructorArgs($params)
    ->getMock();

$anotherClassMock->method('myMethod')
    ->with($data)
    ->willReturn(true);

// 直接将Mock注入someClass实例
$someClass = new someClass($anotherClassMock);
$someClass->run();

方案二:通过Yii容器获取AnotherClass实例(无需改构造函数)

如果不想重构构造函数,修改someClass的run方法,把new替换成从容器获取实例:

public function run()
{
    // 替换new为容器获取实例,传入构造参数
    $anotherClass = \Yii::$container->get(AnotherClass::class, [$params]);
    // more code here ... 
}

这样你原来写的容器注册Mock的代码就能生效了,因为现在是从容器取你注册好的Mock实例,而不是新创建一个AnotherClass对象。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.22 20:39:04