Mockery PHP 完整指南:安装、方法与实战示例

面向初学者的在线Python训练器

轻松学习Python,无需理论负担。在浏览器中直接解决带自动检查的实践任务,无需安装任何东西。

开始课程

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);
    }
}

推荐