PHPUnit 6.5.14 测试时mock其他类方法不生效如何解决?
问题根因
你的Mock不生效的核心原因是Order类的create()方法中硬编码实例化了CreditCardProcessor类,测试中创建的Mock对象完全没有被Order类使用:
- 你在测试代码中构造的
$mockCCP是独立的模拟对象,和业务代码里new CreditCardProcessor()生成的真实实例没有任何关联 - 业务代码调用的始终是真实
CreditCardProcessor类的原生chargeCreditCard()方法,默认返回false,所以断言失败
修复方案
遵循依赖注入原则改造业务代码,将CreditCardProcessor实例从外部传入Order类即可,两种常用实现方式:
方案1:构造函数注入(推荐,适合依赖全局使用的场景)
改造后业务代码
class Order { protected $creditCardProcessor; // 从构造函数传入支付处理器实例,支持传入Mock替换 public function __construct(CreditCardProcessor $processor) { $this->creditCardProcessor = $processor; } public function create() { $success = $this->creditCardProcessor->chargeCreditCard(); return $success; } } class CreditCardProcessor { public function chargeCreditCard() { return false; } }
改造后测试代码
class OrderTest extends TestCase { public function testCreate() { $mockCCP = $this->getMockBuilder(CreditCardProcessor::class) ->setMethods(['chargeCreditCard']) ->getMock(); $mockCCP ->method('chargeCreditCard') ->willReturn(true); // 构造Order时传入模拟的支付处理器 $O = new Order($mockCCP); $success = $O->create(); $this->assertTrue($success, 'Was not able to create order.'); } }
方案2:方法参数注入(适合仅单个方法使用依赖的场景)
改造后业务代码
class Order { // 调用create方法时传入支付处理器实例 public function create(CreditCardProcessor $processor) { $success = $processor->chargeCreditCard(); return $success; } }
改造后测试代码
class OrderTest extends TestCase { public function testCreate() { $mockCCP = $this->getMockBuilder(CreditCardProcessor::class) ->setMethods(['chargeCreditCard']) ->getMock(); $mockCCP ->method('chargeCreditCard') ->willReturn(true); $O = new Order(); // 调用create方法时传入模拟的支付处理器 $success = $O->create($mockCCP); $this->assertTrue($success, 'Was not able to create order.'); } }
内容的提问来源于stack exchange,提问作者Alan P.
相关产品推荐
相关产品推荐

