format integration_tests

This commit is contained in:
Mika 2025-06-17 08:53:23 +02:00
parent 49d27fd8fa
commit 9828ebf86a

View file

@ -1,9 +1,9 @@
use actix_web::{test, web, App}; use actix_web::{App, test, web};
use backend::{controller, Database, build_database_url}; use backend::{Database, build_database_url, controller};
use migration::{Migrator, MigratorTrait}; use migration::{Migrator, MigratorTrait};
use serde_json::json; use serde_json::json;
use serial_test::serial; use serial_test::serial;
use testcontainers::{runners::AsyncRunner, ContainerAsync, ImageExt}; use testcontainers::{ContainerAsync, ImageExt, runners::AsyncRunner};
use testcontainers_modules::{postgres::Postgres, redis::Redis}; use testcontainers_modules::{postgres::Postgres, redis::Redis};
async fn setup_test_environment() -> (ContainerAsync<Postgres>, ContainerAsync<Redis>, Database) { async fn setup_test_environment() -> (ContainerAsync<Postgres>, ContainerAsync<Redis>, Database) {
@ -13,13 +13,13 @@ async fn setup_test_environment() -> (ContainerAsync<Postgres>, ContainerAsync<R
.start() .start()
.await .await
.unwrap(); .unwrap();
let postgres_port = postgres_container.get_host_port_ipv4(5432).await.unwrap(); let postgres_port = postgres_container.get_host_port_ipv4(5432).await.unwrap();
// Start Redis container // Start Redis container
let redis_container = Redis::default().start().await.unwrap(); let redis_container = Redis::default().start().await.unwrap();
let redis_port = redis_container.get_host_port_ipv4(6379).await.unwrap(); let redis_port = redis_container.get_host_port_ipv4(6379).await.unwrap();
// Set environment variables for the application // Set environment variables for the application
unsafe { unsafe {
std::env::set_var("DB_HOST", "127.0.0.1"); std::env::set_var("DB_HOST", "127.0.0.1");
@ -30,17 +30,17 @@ async fn setup_test_environment() -> (ContainerAsync<Postgres>, ContainerAsync<R
std::env::set_var("REDIS_HOST", "127.0.0.1"); std::env::set_var("REDIS_HOST", "127.0.0.1");
std::env::set_var("REDIS_PORT", redis_port.to_string()); std::env::set_var("REDIS_PORT", redis_port.to_string());
} }
// Wait a bit for containers to be ready // Wait a bit for containers to be ready
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await; tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
// Use the existing build_database_url function // Use the existing build_database_url function
let database_url = build_database_url(); let database_url = build_database_url();
let database = Database::new(database_url.into()).await.unwrap(); let database = Database::new(database_url.into()).await.unwrap();
// Run migrations // Run migrations
Migrator::up(database.connection(), None).await.unwrap(); Migrator::up(database.connection(), None).await.unwrap();
(postgres_container, redis_container, database) (postgres_container, redis_container, database)
} }
@ -53,13 +53,14 @@ mod tests {
#[serial] #[serial]
async fn test_user_crud_flow() { async fn test_user_crud_flow() {
let (_pg_container, _redis_container, database) = setup_test_environment().await; let (_pg_container, _redis_container, database) = setup_test_environment().await;
let app = test::init_service( let app = test::init_service(
App::new() App::new()
.app_data(web::Data::new(database.clone())) .app_data(web::Data::new(database.clone()))
.service(web::scope("/api/v1").configure(controller::register_controllers)) .service(web::scope("/api/v1").configure(controller::register_controllers)),
).await; )
.await;
// Test creating a user // Test creating a user
let create_user_payload = json!({ let create_user_payload = json!({
"username": "testuser", "username": "testuser",
@ -67,30 +68,36 @@ mod tests {
"first_name": "Test", "first_name": "Test",
"last_name": "User" "last_name": "User"
}); });
let req = test::TestRequest::post() let req = test::TestRequest::post()
.uri("/api/v1/user") .uri("/api/v1/user")
.set_json(&create_user_payload) .set_json(&create_user_payload)
.to_request(); .to_request();
let resp = test::call_service(&app, req).await; let resp = test::call_service(&app, req).await;
// Log response for debugging // Log response for debugging
let status = resp.status(); let status = resp.status();
let body = test::read_body(resp).await; let body = test::read_body(resp).await;
println!("Create user response: {} - {}", status, String::from_utf8_lossy(&body)); println!(
"Create user response: {} - {}",
status,
String::from_utf8_lossy(&body)
);
if status != StatusCode::CREATED { if status != StatusCode::CREATED {
// Try to get users list to see what endpoints are available // Try to get users list to see what endpoints are available
let req = test::TestRequest::get() let req = test::TestRequest::get().uri("/api/v1/user").to_request();
.uri("/api/v1/user")
.to_request();
let resp = test::call_service(&app, req).await; let resp = test::call_service(&app, req).await;
let resp_status = resp.status(); let resp_status = resp.status();
let body = test::read_body(resp).await; let body = test::read_body(resp).await;
println!("Get users response: {} - {}", resp_status, String::from_utf8_lossy(&body)); println!(
"Get users response: {} - {}",
resp_status,
String::from_utf8_lossy(&body)
);
} }
// For now, just verify the API is responding // For now, just verify the API is responding
assert!(status.is_success() || status.is_client_error()); assert!(status.is_success() || status.is_client_error());
} }
@ -99,34 +106,38 @@ mod tests {
#[serial] #[serial]
async fn test_api_endpoints_respond() { async fn test_api_endpoints_respond() {
let (_pg_container, _redis_container, database) = setup_test_environment().await; let (_pg_container, _redis_container, database) = setup_test_environment().await;
let app = test::init_service( let app = test::init_service(
App::new() App::new()
.app_data(web::Data::new(database.clone())) .app_data(web::Data::new(database.clone()))
.service(web::scope("/api/v1").configure(controller::register_controllers)) .service(web::scope("/api/v1").configure(controller::register_controllers)),
).await; )
.await;
// Test various endpoints to ensure they respond // Test various endpoints to ensure they respond
let endpoints = vec![ let endpoints = vec![
"/api/v1/user", "/api/v1/user",
"/api/v1/project", "/api/v1/project",
"/api/v1/group", "/api/v1/group",
"/api/v1/class", "/api/v1/class",
"/api/v1/template", "/api/v1/template",
]; ];
for endpoint in endpoints { for endpoint in endpoints {
let req = test::TestRequest::get() let req = test::TestRequest::get().uri(endpoint).to_request();
.uri(endpoint)
.to_request();
let resp = test::call_service(&app, req).await; let resp = test::call_service(&app, req).await;
let status = resp.status(); let status = resp.status();
println!("Endpoint {} responded with status: {}", endpoint, status); println!("Endpoint {} responded with status: {}", endpoint, status);
// Verify endpoint is reachable (not 404) // Verify endpoint is reachable (not 404)
assert_ne!(status, StatusCode::NOT_FOUND, "Endpoint {} should exist", endpoint); assert_ne!(
status,
StatusCode::NOT_FOUND,
"Endpoint {} should exist",
endpoint
);
} }
} }
@ -134,37 +145,44 @@ mod tests {
#[serial] #[serial]
async fn test_database_connection() { async fn test_database_connection() {
let (_pg_container, _redis_container, database) = setup_test_environment().await; let (_pg_container, _redis_container, database) = setup_test_environment().await;
// Test that we can connect to the database // Test that we can connect to the database
let connection = database.connection(); let connection = database.connection();
assert!(connection.ping().await.is_ok(), "Database should be reachable"); assert!(
connection.ping().await.is_ok(),
"Database should be reachable"
);
} }
#[actix_web::test] #[actix_web::test]
#[serial] #[serial]
async fn test_invalid_endpoints_return_404() { async fn test_invalid_endpoints_return_404() {
let (_pg_container, _redis_container, database) = setup_test_environment().await; let (_pg_container, _redis_container, database) = setup_test_environment().await;
let app = test::init_service( let app = test::init_service(
App::new() App::new()
.app_data(web::Data::new(database.clone())) .app_data(web::Data::new(database.clone()))
.service(web::scope("/api/v1").configure(controller::register_controllers)) .service(web::scope("/api/v1").configure(controller::register_controllers)),
).await; )
.await;
// Test non-existent endpoints // Test non-existent endpoints
let invalid_endpoints = vec![ let invalid_endpoints = vec![
"/api/v1/nonexistent", "/api/v1/nonexistent",
"/api/v1/user/invalid/path", "/api/v1/user/invalid/path",
"/api/v2/user", "/api/v2/user",
]; ];
for endpoint in invalid_endpoints { for endpoint in invalid_endpoints {
let req = test::TestRequest::get() let req = test::TestRequest::get().uri(endpoint).to_request();
.uri(endpoint)
.to_request();
let resp = test::call_service(&app, req).await; let resp = test::call_service(&app, req).await;
assert_eq!(resp.status(), StatusCode::NOT_FOUND, "Invalid endpoint {} should return 404", endpoint); assert_eq!(
resp.status(),
StatusCode::NOT_FOUND,
"Invalid endpoint {} should return 404",
endpoint
);
} }
} }
} }