Integrationstests für Rust mit Docker: Vollständiger Leitfaden

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Integrationstests von Rust mit Docker: Von der Theorie zur Praxis



Moderne Rust-Entwicklung erfordert nicht nur die Überprüfung einzelner Funktionen (Unit-Tests), sondern auch das Testen der Interaktion von Komponenten mit externen Diensten – Datenbanken, Caches, APIs. Integrationstests mit Docker ermöglichen es, die Umgebung zu isolieren, Reproduzierbarkeit zu gewährleisten und Probleme mit "funktioniert auf meinem Rechner" zu vermeiden. In diesem Artikel werden wir untersuchen, wie man Integrationstests für Rust-Anwendungen mit Docker einrichtet.



Warum Docker für Integrationstests von Rust?

Docker löst drei zentrale Probleme:

  • Umgebungsisolierung – Tests werden in einem sauberen Container ausgeführt, ohne Einfluss lokaler Einstellungen
  • Reproduzierbarkeit – identische Bedingungen auf allen Entwicklerrechnern und in CI/CD
  • Abhängigkeitsverwaltung – automatischer Start von PostgreSQL, Redis, Kafka und anderen Diensten


Projektkonfiguration: Struktur und Abhängigkeiten

Wir erstellen ein Projekt mit Integrationstests für einen Webserver auf Actix-web, der mit PostgreSQL arbeitet.



# Cargo.toml[package]name = "rust-docker-testing"version = "0.1.0"edition = "2021"

[dependencies]actix-web = "4"serde = { version = "1", features = ["derive"] }tokio = { version = "1", features = ["full"] }sqlx = { version = "0.7", features = ["runtime-tokio", "postgres"] }dotenv = "0.15"

[dev-dependencies]testcontainers = "0.14"reqwest = { version = "0.11", features = ["json"] }


Beachten Sie testcontainers – dies ist eine Rust-Bibliothek zur Verwaltung von Docker-Containern direkt aus den Tests.



Projektstruktur

Empfohlene Struktur für Integrationstests:

.├── src/│   ├── main.rs│   ├── lib.rs│   ├── models.rs│   └── handlers.rs├── tests/│   ├── common/│   │   └── mod.rs          # Gemeinsame Hilfsfunktionen für Tests│   ├── integration_tests.rs # Hauptintegrationstests│   └── docker-compose.yml  # Für manuellen Start├── Dockerfile└── .env


Schritt 1: Schreiben eines Integrationstests mit Docker

Wir erstellen einen Test, der PostgreSQL in Docker startet, Migrationen ausführt und die API überprüft.



// tests/integration_tests.rsuse testcontainers::clients;use testcontainers::images::postgres::Postgres;use sqlx::postgres::PgPoolOptions;use std::net::TcpListener;

async fn setup_test_db() -> (String, testcontainers::Container) { let docker = clients::Cli::default(); let postgres_image = Postgres::default(); let container = docker.run(postgres_image); let host = container.get_host().unwrap(); let port = container.get_host_port_ipv4(5432).unwrap(); let database_url = format!("postgres://postgres:postgres@{}:{}/postgres", host, port); // Migrationen ausführen let pool = PgPoolOptions::new() .max_connections(5) .connect(&database_url) .await .expect("Verbindung zu Postgres fehlgeschlagen"); sqlx::query("CREATE TABLE IF NOT EXISTS users (id SERIAL PRIMARY KEY, name VARCHAR(255) NOT NULL)") .execute(&pool) .await .expect("Migration fehlgeschlagen"); (database_url, container)}

#[tokio::test]async fn test_create_user() { let (db_url, _container) = setup_test_db().await; // Anwendung auf zufälligem Port starten let listener = TcpListener::bind("127.0.0.1:0").unwrap(); let port = listener.local_addr().unwrap().port(); let server = actix_web::HttpServer::new(move || { actix_web::App::new() .app_data(actix_web::web::Data::new(db_url.clone())) .route("/users", actix_web::web::post().to(handlers::create_user)) }) .listen(listener) .unwrap() .run(); tokio::spawn(server); // Serverstart abwarten tokio::ti

Blogs

Buchempfehlungen