使用 Docker 进行 PHP 集成测试:高级技术

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

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

开始课程

使用 Docker 进行 PHP 集成测试:高级水平

集成测试是开发过程中至关重要的一环,特别是对于与数据库、队列、外部 API 和其他服务交互的复杂 PHP 应用程序。Docker 允许搭建一个尽可能接近生产环境的隔离环境,并在可重现的条件下执行测试。在本文中,我们将探讨高级技术:测试容器的组织、外部依赖的模拟、并行执行以及与 CI/CD 的集成。



1. 使用 docker-compose 的测试环境架构

对于集成测试,我们使用一个单独的 docker-compose.test.yml 文件,它仅启动必要的服务:包含测试代码的 PHP-FPM、数据库(例如 PostgreSQL)、Redis,以及可选的外部 API 模拟服务器。

version: '3.8'services:  php-test:    build:      context: .      dockerfile: Dockerfile.test    volumes:      - .:/var/www/html    environment:      DATABASE_URL: "pgsql://test:test@db-test:5432/testdb"      REDIS_URL: "redis://redis-test:6379"      EXTERNAL_API_URL: "http://mock-server:1080"    depends_on:      - db-test      - redis-test      - mock-server

db-test: image: postgres:15-alpine environment: POSTGRES_DB: testdb POSTGRES_USER: test POSTGRES_PASSWORD: test ports: - "5433:5432" # 避免与主数据库冲突

redis-test: image: redis:7-alpine ports: - "6380:6379"

mock-server: image: mockserver/mockserver:latest environment: MOCKSERVER_PROPERTY_FILE: /config/mockserver.properties volumes: - ./tests/mockserver:/config ports: - "1080:1080"

请注意:我们为测试服务使用单独的端口,以避免干扰本地开发。



2. 准备 PHPUnit 并初始化测试数据库

为集成测试配置 phpunit.xml:

<phpunit bootstrap="tests/bootstrap.php">    <testsuites>        <testsuite name="Integration">            <directory>tests/Integration</directory>        </testsuite>    </testsuites>    <php>        <env name="APP_ENV" value="test"/>        <env name="KERNEL_CLASS" value="App\\Kernel"/>    </php></phpunit>

tests/bootstrap.php 文件负责初始化数据库模式并填充测试数据:

require __DIR__ . '/../vendor/autoload.php';

// 创建数据库模式$pdo = new PDO('pgsql:host=db-test;port=5432;dbname=testdb', 'test', 'test');$pdo->exec(file_get_contents(__DIR__ . '/../migrations/schema.sql'));

// 加载测试夹具require __DIR__ . '/Fixtures/LoadFixtures.php';

这种方法确保每次测试运行都从一个干净、可预测的状态开始。



3. 使用外部 API 进行测试:MockServer 和 WireMock

为了模拟外部 HTTP 服务,我们使用 MockServer(或 WireMock)。在 JSON 文件中创建期望配置:

// tests/mockserver/expectations/payment.json{  "httpRequest": {    "method": "POST",    "path": "/api/v1/charge"  },  "httpResponse": {    "statusCode": 200,    "body": "{\\"status\\": \\"success\\", \\"transaction_id\\": \\"txn_123\\"}",    "headers": {      "Content-Type": "application/json"    }  }}

在 PHP 测试代码中,我们向一个真实的 URL 发送请求,该 URL 通过环境变量指向模拟服务器:

class PaymentIntegrationTest extends TestCase{    private PaymentService $paymentService;

protected function setUp(): void { $this->paymentService = new PaymentService( new HttpClient(['base_uri' => $_ENV['EXTERNAL_API_URL']])

博客

书籍推荐