如何在setUp函数中使用Mock改写PHPUnit单元测试?
为Zend 2的NullMetricsClientFactory编写带Mock的PHPUnit测试
我目前有一个基础的PHPUnit测试,包含一个setUp方法和两个测试用例——还在学习PHPUnit,若有疏漏请多包涵:) 注:我使用的是Zend 2框架。我想给下面的测试加入Mock,但不知道具体怎么操作:
<?php namespace AcmeTest\MetricsClient\Zend; use Acme\MetricsClient\NullMetricsClient; use Acme\MetricsClient\Zend\NullMetricsClientFactory; use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\ServiceManager; class NullMetricsClientFactoryTest extends \PHPUnit_Framework_TestCase { private $serviceManager; private $factory; protected function setUp() { $this->factory = new NullMetricsClientFactory(); $this->serviceManager = new ServiceManager(); } public function testIsZf2Factory() { $this->assertInstanceOf(FactoryInterface::class, $this->factory); } public function testCreatesNullMetricsClientService() { $nullClient = $this->factory->createService($this->serviceManager); $this->assertInstanceOf(NullMetricsClient::class, $nullClient); } }
改造方案:引入Mock替代真实ServiceManager
单元测试的核心是隔离依赖,我们可以用PHPUnit的Mock功能替代真实的ServiceManager实例,避免创建完整服务管理器带来的额外开销,同时精准控制依赖行为。
修改后的测试代码:
<?php namespace AcmeTest\MetricsClient\Zend; use Acme\MetricsClient\NullMetricsClient; use Acme\MetricsClient\Zend\NullMetricsClientFactory; use Zend\ServiceManager\FactoryInterface; use Zend\ServiceManager\ServiceManager; class NullMetricsClientFactoryTest extends \PHPUnit_Framework_TestCase { private $serviceManagerMock; private $factory; protected function setUp() { $this->factory = new NullMetricsClientFactory(); // 创建ServiceManager的Mock实例,禁用原始构造函数 $this->serviceManagerMock = $this->getMockBuilder(ServiceManager::class) ->disableOriginalConstructor() ->getMock(); } public function testIsZf2Factory() { $this->assertInstanceOf(FactoryInterface::class, $this->factory); } public function testCreatesNullMetricsClientService() { // 调用工厂的createService,传入Mock的服务管理器 $nullClient = $this->factory->createService($this->serviceManagerMock); $this->assertInstanceOf(NullMetricsClient::class, $nullClient); } }
关键说明:
- 创建Mock实例:使用
getMockBuilder(ServiceManager::class)构建Mock,disableOriginalConstructor()避免调用真实的ServiceManager构造函数(真实构造可能加载配置、初始化服务,这些在单元测试中不需要)。 - 替换真实依赖:把原来的真实
ServiceManager实例换成Mock实例,实现依赖隔离。 - 扩展场景:如果后续
NullMetricsClientFactory需要从ServiceManager获取其他服务(比如配置),可以给Mock添加方法预期,例如:
// 模拟ServiceManager返回指定配置数据 $this->serviceManagerMock->expects($this->once()) ->method('get') ->with('Config') ->willReturn(['metrics' => ['enabled' => false]]);
这样就能测试工厂在不同配置下的行为。
内容的提问来源于stack exchange,提问作者Zabs
相关产品推荐
相关产品推荐

