Mockery框架入门:简单示例解析
概述
Mockery是一个流行的PHP模拟对象框架,它可以帮助开发者创建测试替身(Test Doubles)来隔离被测代码的依赖项。本文将通过一个温度计算器的简单示例,展示如何使用Mockery进行单元测试。
场景设定
假设我们有一个Temperature
类,它负责从某个服务获取温度读数并计算平均值。这个服务可能是一个Web服务或其他数据源,但在测试时我们并不需要真实的实现。
class Temperature
{
private $service;
public function __construct($service)
{
$this->service = $service;
}
public function average()
{
$total = 0;
for ($i=0; $i<3; $i++) {
$total += $this->service->readTemp();
}
return $total/3;
}
}
测试需求分析
我们需要测试Temperature
类的average()
方法,但面临两个问题:
- 真实的温度服务可能不可用或速度慢
- 真实的温度服务返回结果不可预测
这正是Mockery发挥作用的地方——我们可以创建一个模拟的温度服务,完全控制它的行为。
使用Mockery创建测试
use \Mockery;
class TemperatureTest extends \PHPUnit\Framework\TestCase
{
public function tearDown()
{
Mockery::close();
}
public function testGetsAverageTemperatureFromThreeServiceReadings()
{
// 1. 创建模拟服务
$service = Mockery::mock('service');
// 2. 设置预期行为
$service->shouldReceive('readTemp')
->times(3) // 预期被调用3次
->andReturn(10, 12, 14); // 三次调用分别返回10,12,14
// 3. 注入模拟服务并测试
$temperature = new Temperature($service);
$this->assertEquals(12, $temperature->average());
}
}
代码解析
-
创建模拟对象:
Mockery::mock('service')
创建了一个模拟的温度服务对象。 -
设置预期:
shouldReceive('readTemp')
:预期会调用readTemp
方法times(3)
:预期会被调用3次andReturn(10, 12, 14)
:三次调用分别返回10、12、14
-
测试验证:我们验证当输入这三个值时,平均值计算是否正确。
-
清理工作:
tearDown()
中的Mockery::close()
会验证所有预期是否满足,并清理模拟对象。
技术要点
-
行为验证:Mockery不仅检查返回值,还验证了方法调用的次数,这是单元测试中重要的行为验证。
-
隔离测试:通过模拟依赖项,我们可以专注于测试
Temperature
类的逻辑,而不受外部服务影响。 -
确定性测试:使用固定返回值确保了测试的可重复性和确定性。
进阶提示
在实际项目中,你可能会使用Mockery的更多高级功能:
- 参数匹配:验证方法调用时传入的参数
- 调用顺序:验证多个方法调用的顺序
- 异常模拟:模拟方法抛出异常的情况
总结
通过这个简单示例,我们展示了Mockery的基本用法:创建模拟对象、设置预期行为、验证结果。这种技术对于构建可靠、隔离的单元测试至关重要,特别是当代码依赖外部服务或复杂组件时。
Mockery的强大之处在于它简洁的API和灵活的配置选项,这使得编写和维护测试变得更加容易。随着项目复杂度的增加,你会发现Mockery能够处理各种复杂的测试场景。
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考