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

