test: refusing fakes, failure-path tests, shared panic stubs
This commit is contained in:
@@ -129,3 +129,27 @@ async fn edit_sets_watch_medium() {
|
||||
let updated = reviews.get_review_by_id(&review_id).await.unwrap().unwrap();
|
||||
assert_eq!(updated.watch_medium(), Some(&WatchMedium::Cinema));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn editing_a_review_fails_when_the_store_refuses() {
|
||||
let (_, events, review_id, user_id) = setup().await;
|
||||
let deps = EditReviewDeps {
|
||||
review: Arc::new(domain::testing::RefusingReviewRepository),
|
||||
event_publisher: Arc::clone(&events) as _,
|
||||
};
|
||||
|
||||
let result = edit_review::execute(
|
||||
&deps,
|
||||
EditReviewCommand {
|
||||
review_id: review_id.value(),
|
||||
requesting_user_id: user_id.value(),
|
||||
..edit_review_command(5)
|
||||
},
|
||||
)
|
||||
.await;
|
||||
|
||||
assert!(matches!(
|
||||
result,
|
||||
Err(domain::errors::DomainError::InfrastructureError(m)) if m == "refused"
|
||||
));
|
||||
}
|
||||
|
||||
@@ -220,3 +220,47 @@ async fn publishes_movie_discovered_for_new_movie_with_external_id() {
|
||||
"should publish MovieEnrichmentRequested"
|
||||
);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn logging_a_review_fails_when_the_review_store_refuses() {
|
||||
let movies = InMemoryStore::new();
|
||||
let logger = DefaultReviewLogger::new(
|
||||
Arc::clone(&movies) as _,
|
||||
Arc::clone(&movies) as _,
|
||||
Arc::new(domain::testing::RefusingReviewRepository),
|
||||
Arc::clone(&movies) as _,
|
||||
Arc::new(FakeMetadataClient),
|
||||
NoopEventPublisher::new(),
|
||||
);
|
||||
|
||||
let result = logger
|
||||
.log_review(log_review_command_manual(Uuid::new_v4(), "Test Film", 2024))
|
||||
.await;
|
||||
|
||||
assert!(matches!(result, Err(DomainError::InfrastructureError(m)) if m == "refused"));
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn logging_a_review_when_event_publishing_fails_returns_the_error_but_keeps_the_saved_review()
|
||||
{
|
||||
let movies = InMemoryStore::new();
|
||||
let logger = DefaultReviewLogger::new(
|
||||
Arc::clone(&movies) as _,
|
||||
Arc::clone(&movies) as _,
|
||||
Arc::clone(&movies) as _,
|
||||
Arc::clone(&movies) as _,
|
||||
Arc::new(FakeMetadataClient),
|
||||
Arc::new(domain::testing::RefusingEventPublisher),
|
||||
);
|
||||
|
||||
let result = logger
|
||||
.log_review(log_review_command_manual(Uuid::new_v4(), "Test Film", 2024))
|
||||
.await;
|
||||
|
||||
assert!(matches!(result, Err(DomainError::InfrastructureError(m)) if m == "refused"));
|
||||
assert_eq!(
|
||||
movies.review_count(),
|
||||
1,
|
||||
"review is saved before publishing"
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
use domain::testing::test_movie_with_year;
|
||||
use domain::testing::{NoopPersonCommand, test_movie_with_year};
|
||||
use std::sync::Arc;
|
||||
|
||||
use chrono::Utc;
|
||||
@@ -61,31 +61,6 @@ async fn stores_profile_and_indexes() {
|
||||
assert_eq!(profile_repo.movie_profile_count(), 1);
|
||||
}
|
||||
|
||||
struct NoopPersonCommand;
|
||||
|
||||
#[async_trait::async_trait]
|
||||
impl domain::ports::PersonCommand for NoopPersonCommand {
|
||||
async fn upsert_batch(
|
||||
&self,
|
||||
_: &[domain::models::Person],
|
||||
) -> Result<(), domain::errors::DomainError> {
|
||||
Ok(())
|
||||
}
|
||||
async fn backfill_from_credits_batch(
|
||||
&self,
|
||||
_: u32,
|
||||
) -> Result<(u64, bool), domain::errors::DomainError> {
|
||||
Ok((0, false))
|
||||
}
|
||||
async fn update_enrichment(
|
||||
&self,
|
||||
_: &domain::models::PersonId,
|
||||
_: &domain::models::PersonEnrichmentData,
|
||||
) -> Result<(), domain::errors::DomainError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn extracts_and_indexes_persons() {
|
||||
let movie_repo = InMemoryStore::new();
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
use super::*;
|
||||
use async_trait::async_trait;
|
||||
use domain::testing::NoopAckHandle;
|
||||
use domain::value_objects::{ExternalMetadataId, MovieId};
|
||||
use domain::{
|
||||
errors::DomainError,
|
||||
@@ -8,18 +9,6 @@ use domain::{
|
||||
use futures::{stream, stream::BoxStream};
|
||||
use std::sync::{Arc, Mutex};
|
||||
|
||||
struct NoopAck;
|
||||
|
||||
#[async_trait]
|
||||
impl AckHandle for NoopAck {
|
||||
async fn ack(&self) -> Result<(), DomainError> {
|
||||
Ok(())
|
||||
}
|
||||
async fn nack(&self) -> Result<(), DomainError> {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
struct TrackingAck {
|
||||
acked: Arc<Mutex<bool>>,
|
||||
nacked: Arc<Mutex<bool>>,
|
||||
@@ -47,7 +36,7 @@ impl EventConsumer for VecConsumer {
|
||||
.events
|
||||
.iter()
|
||||
.cloned()
|
||||
.map(|e| Ok(EventEnvelope::new(e, Box::new(NoopAck))))
|
||||
.map(|e| Ok(EventEnvelope::new(e, Box::new(NoopAckHandle))))
|
||||
.collect();
|
||||
Box::pin(stream::iter(envelopes))
|
||||
}
|
||||
|
||||
@@ -90,3 +90,21 @@ async fn test_add_to_watchlist_movie_not_found_by_id() {
|
||||
|
||||
assert!(add::execute(&deps, cmd).await.is_err());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn adding_the_same_movie_to_a_watchlist_twice_keeps_a_single_entry_and_succeeds() {
|
||||
let movies = InMemoryStore::new();
|
||||
let movie = test_movie_with_year("Heat", 1995);
|
||||
let movie_uuid = movie.id().value();
|
||||
let user_id = uuid::Uuid::new_v4();
|
||||
movies.upsert_movie(&movie).await.unwrap();
|
||||
let deps = make_deps(Arc::clone(&movies), Arc::clone(&movies));
|
||||
|
||||
for _ in 0..2 {
|
||||
add::execute(&deps, add_to_watchlist_command(user_id, movie_uuid))
|
||||
.await
|
||||
.expect("second add must not error");
|
||||
}
|
||||
|
||||
assert_eq!(movies.watchlist_count(), 1);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user