feat: domain mocks, TestContextBuilder, use case tests, factory pattern

- Add test-helpers feature to domain crate with in-memory mocks and panic stubs for all ports
- Add TestContextBuilder to application crate for zero-database test setup
- Add unit tests for log_review, register, login, add_to_watchlist, delete_review use cases
- Extract DatabaseAdapters factory and build_* helpers into presentation/src/factory.rs
- Refactor wire_dependencies() in main.rs to use factory module
This commit is contained in:
2026-05-14 00:41:25 +02:00
parent e41d85bd7e
commit edc1f6c850
14 changed files with 1458 additions and 96 deletions

View File

@@ -37,3 +37,92 @@ pub async fn execute(ctx: &AppContext, query: LoginQuery) -> Result<LoginResult,
expires_at: generated.expires_at,
})
}
#[cfg(test)]
mod tests {
use std::sync::Arc;
use domain::models::UserRole;
use domain::testing::InMemoryUserRepository;
use crate::{
commands::RegisterCommand,
queries::LoginQuery,
test_helpers::TestContextBuilder,
use_cases::{login, register},
};
async fn setup_user(ctx: &crate::context::AppContext, email: &str, password: &str) {
register::execute(
ctx,
RegisterCommand {
email: email.to_string(),
username: "testuser".to_string(),
password: password.to_string(),
role: UserRole::Standard,
},
)
.await
.unwrap();
}
#[tokio::test]
async fn test_login_valid_credentials_returns_token() {
let users = InMemoryUserRepository::new();
let ctx = TestContextBuilder::new()
.with_users(Arc::clone(&users) as _)
.build();
setup_user(&ctx, "carol@example.com", "secret123").await;
let result = login::execute(
&ctx,
LoginQuery {
email: "carol@example.com".into(),
password: "secret123".into(),
},
)
.await
.unwrap();
assert!(!result.token.is_empty());
assert_eq!(result.email, "carol@example.com");
}
#[tokio::test]
async fn test_login_wrong_password_fails() {
let users = InMemoryUserRepository::new();
let ctx = TestContextBuilder::new()
.with_users(Arc::clone(&users) as _)
.build();
setup_user(&ctx, "dave@example.com", "correct_password").await;
let result = login::execute(
&ctx,
LoginQuery {
email: "dave@example.com".into(),
password: "wrong_password".into(),
},
)
.await;
assert!(result.is_err());
}
#[tokio::test]
async fn test_login_unknown_email_fails() {
let ctx = TestContextBuilder::new().build();
let result = login::execute(
&ctx,
LoginQuery {
email: "nobody@example.com".into(),
password: "anything".into(),
},
)
.await;
assert!(result.is_err());
}
}