使用Docker进行Rust集成测试:完整指南

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

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

开始课程

使用Docker进行Rust集成测试:从A到Z



集成测试是开发可靠Rust应用程序的关键阶段。与单元测试不同,集成测试检查组件与外部依赖项(如数据库、缓存、消息队列)的交互。Docker非常适合创建隔离、可重现的测试环境。在本文中,我们将探讨如何使用Docker配置Rust项目的集成测试,从基本架构到CI/CD。



1. 为什么Docker是Rust集成测试的最佳选择



Rust编译为原生代码,但其应用程序通常依赖外部服务。Docker解决了三个关键问题:

  • 隔离性:每个测试在干净的容器中运行,排除先前运行的影响。
  • 可重现性:精确版本的PostgreSQL、Redis或Kafka确保在本地机器和CI中行为一致。
  • 速度:Docker镜像被缓存,Rust测试只编译一次。


考虑一个典型项目:基于Actix-web的Web服务器,使用PostgreSQL。我们的目标是编写一个测试,启动一个数据库容器,执行迁移并检查CRUD操作。



2. 使用Docker Compose配置测试基础设施



为方便起见,我们使用docker-compose.yml来描述所有依赖项。在项目根目录创建文件:



version: '3.8'services:  postgres_test:    image: postgres:15-alpine    environment:      POSTGRES_USER: test_user      POSTGRES_PASSWORD: test_pass      POSTGRES_DB: test_db    ports:      - "5433:5432"    tmpfs: /var/lib/postgresql/data  # 数据在内存中以提高速度


注意tmpfs——这可以加速测试,因为数据不会写入磁盘。选择端口5433是为了避免与本地数据库冲突。



现在编写一个Rust函数来管理容器。使用testcontainers crate——它允许以编程方式启动Docker容器:



// tests/common/mod.rsuse testcontainers::{clients, images::postgres::Postgres, Container};

pub struct TestDb { pub container: Container<'static, Postgres>, pub connection_string: String,}

impl TestDb { pub fn new() -> Self { let docker = clients::Cli::default(); let postgres_image = Postgres::default(); let container = docker.run(postgres_image); let host = container.get_host(); let port = container.get_host_port_ipv4(5432); let connection_string = format!( "postgres://postgres:postgres@{}:{}/postgres", host, port ); TestDb { container, connection_string } }}


这个模块可以在所有集成测试中重用。容器在测试失败或进程结束时自动删除。



3. 编写带有真实请求的集成测试



创建一个测试,检查用户的插入和读取。假设我们在主代码中有User结构体和create_user和get_user函数。



// tests/integration_test.rsmod common;

use sqlx::PgPool;use your_crate::{create_user, get_user, User};

#[tokio::test]async fn test_create_and_get_user() { let test_db = common::TestDb::new(); let pool = PgPool::connect(&test_db.connection_string) .await .expect("Failed to connect to DB"); // 执行迁移(如果使用sqlx) sqlx::migrate!().run(&pool).await.unwrap(); // 创建用户 let user = User { name: "Alice".into(), email: "alice@example.com".into(), }; let created = create_user(&pool, &us

博客

书籍推荐