Mockery PHP 完整指南:从入门到实战
1. 什么是 Mockery?为什么需要它?
Mockery 是一个强大且灵活的 PHP 模拟对象(mock objects)库,专为单元测试(unit testing)设计。它帮助开发者隔离被测试代码与其依赖项。与其使用真实对象(如数据库连接、API 客户端或文件系统),你可以创建它们的“替身”(mocks),模拟原始对象的行为。这让测试变得快速、可靠,且不受外部因素影响。
为什么需要它?假设你在测试一个 OrderProcessor 类,它在订单完成后发送邮件。如果使用真实的 Mailer,测试会变慢,依赖 SMTP 服务器的可用性,甚至可能意外向真实用户发送邮件。借助 Mockery,你可以创建一个“假”的 Mailer,仅验证 send() 方法是否被正确参数调用。这样,你就能专注于测试 OrderProcessor 的核心逻辑,而非基础设施。
Mockery 不仅仅是对象替换。它提供了丰富的 API 来定义期望(expectations):你可以指定方法被调用的次数、参数、顺序以及返回值。这不仅让测试隔离,还使其具备自文档化能力,因为期望明确描述了对象间的交互。
2. 安装 Mockery
Mockery 通过 Composer(PHP 的标准包管理器)安装。建议将其作为开发依赖(require-dev)安装,因为生产环境不需要它。
composer require --dev mockery/mockery
安装后,请确保你的 composer.json 文件在 require-dev 部分包含以下内容:
{
"require-dev": {
"mockery/mockery": "^1.6"
}
}
如果你使用 PHPUnit,Mockery 通过 \Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration trait 实现开箱即用的集成。
3. 快速上手:第一个 Mockery 测试
让我们创建一个简单的测试,演示 Mockery 的基本功能。假设我们有一个 Calculator 类,它依赖于 Logger 服务。
<?php
// 示例类
interface Logger {
public function log(string $message): void;
}
class Calculator {
private Logger $logger;
public function __construct(Logger $logger) {
$this->logger = $logger;
}
public function add(int $a, int $b): int {
$result = $a + $b;
$this->logger->log("Adding $a and $b, result: $result");
return $result;
}
}
// 使用 Mockery 的测试
use PHPUnit\Framework\TestCase;
use Mockery\Adapter\Phpunit\MockeryPHPUnitIntegration;
class CalculatorTest extends TestCase {
use MockeryPHPUnitIntegration;
public function testAddLogsCorrectly(): void {
// 1. 为 Logger 创建模拟对象
$loggerMock = Mockery::mock(Logger::class);
// 2. 定义期望:log() 方法应被调用 1 次,且带有特定消息
$loggerMock->shouldReceive('log')
->once()
->with('Adding 2 and 3, result: 5');
// 3. 使用模拟对象创建被测类
$calculator = new Calculator($loggerMock);
// 4. 执行测试
$result = $calculator->add(2, 3);
$this->assertEquals(5, $result);
}
}