test: cascading in-memory store

This commit is contained in:
2026-10-25 22:19:24 +01:00
parent 51d92e08a7
commit 06eec2feae
72 changed files with 2439 additions and 1627 deletions

View File

@@ -5,10 +5,7 @@ use chrono::Utc;
use domain::{
models::MovieProfile,
ports::MovieCommand,
testing::{
FakeSearchCommand, InMemoryMovieProfileRepository, InMemoryMovieRepository,
PanicPersonCommand,
},
testing::{FakeSearchCommand, InMemoryStore, PanicPersonCommand},
value_objects::MovieId,
};
@@ -16,8 +13,8 @@ use crate::movies::{commands::EnrichMovieCommand, deps::EnrichMovieDeps, enrich_
#[tokio::test]
async fn stores_profile_and_indexes() {
let movie_repo = InMemoryMovieRepository::new();
let profile_repo = InMemoryMovieProfileRepository::new();
let movie_repo = InMemoryStore::new();
let profile_repo = Arc::clone(&movie_repo);
// PanicPersonCommand is safe here — empty cast/crew means upsert_batch is never called
let movie = test_movie_with_year("Test", 2024);
@@ -61,7 +58,7 @@ async fn stores_profile_and_indexes() {
.await
.unwrap();
assert_eq!(profile_repo.count(), 1);
assert_eq!(profile_repo.movie_profile_count(), 1);
}
struct NoopPersonCommand;
@@ -91,8 +88,8 @@ impl domain::ports::PersonCommand for NoopPersonCommand {
#[tokio::test]
async fn extracts_and_indexes_persons() {
let movie_repo = InMemoryMovieRepository::new();
let profile_repo = InMemoryMovieProfileRepository::new();
let movie_repo = InMemoryStore::new();
let profile_repo = Arc::clone(&movie_repo);
let movie = test_movie_with_year("Cast Movie", 2024);
let movie_id = MovieId::from_uuid(movie.id().value());
@@ -147,5 +144,5 @@ async fn extracts_and_indexes_persons() {
.await
.unwrap();
assert_eq!(profile_repo.count(), 1);
assert_eq!(profile_repo.movie_profile_count(), 1);
}

View File

@@ -4,7 +4,7 @@ use uuid::Uuid;
use domain::{
models::{CastMember, CrewMember, MovieProfile},
ports::MovieProfileRepository,
testing::InMemoryMovieProfileRepository,
testing::InMemoryStore,
value_objects::MovieId,
};
@@ -13,7 +13,7 @@ use crate::movies::get_movie_profile::{self, GetMovieProfileQuery};
#[tokio::test]
async fn returns_none_when_no_profile() {
let movie_profile = InMemoryMovieProfileRepository::new();
let movie_profile = InMemoryStore::new();
let deps = GetMovieProfileDeps { movie_profile };
let result = get_movie_profile::execute(
@@ -30,7 +30,7 @@ async fn returns_none_when_no_profile() {
#[tokio::test]
async fn returns_profile_with_cast_and_crew() {
let profile_repo = InMemoryMovieProfileRepository::new();
let profile_repo = InMemoryStore::new();
let movie_id = MovieId::generate();
let profile = MovieProfile {

View File

@@ -1,10 +1,10 @@
use domain::testing::InMemoryMovieRepository;
use domain::testing::InMemoryStore;
use crate::movies::{deps::GetMoviesDeps, get_movies, queries::GetMoviesQuery};
#[tokio::test]
async fn returns_empty_when_no_movies() {
let movie = InMemoryMovieRepository::new();
let movie = InMemoryStore::new();
let deps = GetMoviesDeps { movie };
let result = get_movies::execute(

View File

@@ -6,7 +6,7 @@ use domain::{
errors::DomainError,
models::MovieProfile,
ports::{MovieEnrichmentClient, MovieProfileRepository},
testing::{FakeMovieEnrichmentClient, InMemoryMovieProfileRepository},
testing::{FakeMovieEnrichmentClient, InMemoryStore},
value_objects::MovieId,
};
@@ -15,7 +15,7 @@ use crate::movies::request_enrichment;
#[tokio::test]
async fn returns_profile_when_none_cached() {
let enrichment = FakeMovieEnrichmentClient;
let profile_repo = InMemoryMovieProfileRepository::new();
let profile_repo = InMemoryStore::new();
let movie_id = MovieId::generate();
let result = request_enrichment::fetch_if_stale(
@@ -34,7 +34,7 @@ async fn returns_profile_when_none_cached() {
#[tokio::test]
async fn returns_none_when_profile_is_fresh() {
let enrichment = FakeMovieEnrichmentClient;
let profile_repo = InMemoryMovieProfileRepository::new();
let profile_repo = InMemoryStore::new();
let movie_id = MovieId::generate();
// Seed a fresh profile (enriched_at = now)
@@ -87,7 +87,7 @@ impl MovieEnrichmentClient for NotFoundEnrichmentClient {
#[tokio::test]
async fn returns_none_on_not_found_from_client() {
let enrichment = NotFoundEnrichmentClient;
let profile_repo = InMemoryMovieProfileRepository::new();
let profile_repo = InMemoryStore::new();
let movie_id = MovieId::generate();
let result = request_enrichment::fetch_if_stale(

View File

@@ -8,10 +8,7 @@ use domain::{
errors::DomainError,
models::Movie,
ports::{MetadataClient, MovieCommand, MovieQuery},
testing::{
FakeSearchCommand, InMemoryMovieProfileRepository, InMemoryMovieRepository,
NoopEventPublisher, NoopObjectStorage,
},
testing::{FakeSearchCommand, InMemoryStore, NoopEventPublisher, NoopObjectStorage},
value_objects::{ExternalMetadataId, PosterUrl},
};
@@ -19,9 +16,9 @@ use crate::movies::{deps::SyncPosterDeps, sync_poster};
fn default_deps() -> SyncPosterDeps {
SyncPosterDeps {
movie_command: InMemoryMovieRepository::new(),
movie_query: InMemoryMovieRepository::new(),
movie_profile: InMemoryMovieProfileRepository::new(),
movie_command: InMemoryStore::new(),
movie_query: InMemoryStore::new(),
movie_profile: InMemoryStore::new(),
metadata: Arc::new(domain::testing::FakeMetadataClient),
poster_fetcher: Arc::new(domain::testing::FakePosterFetcher),
object_storage: Arc::new(NoopObjectStorage),
@@ -41,7 +38,7 @@ async fn fails_when_movie_not_found() {
#[tokio::test]
async fn fails_when_no_external_id() {
let movies = InMemoryMovieRepository::new();
let movies = InMemoryStore::new();
let movie = test_movie_with_year("Test", 2024);
let movie_id = movie.id().value();
movies.upsert_movie(&movie).await.unwrap();
@@ -79,7 +76,7 @@ impl MetadataClient for FakeMetaWithPoster {
#[tokio::test]
async fn syncs_poster_for_movie_with_external_id() {
let movies = InMemoryMovieRepository::new();
let movies = InMemoryStore::new();
let ext_id = ExternalMetadataId::new("tmdb:999".into()).unwrap();
let movie = test_movie_with_external_id("Poster Movie", 2024, ext_id);
let movie_id = movie.id().value();