//! L1 tests for [`HealthUseCase`] driven entirely through **mocked/fake ports** //! (`FixedClock`, `SeqIdGenerator`, a spy `EventBus`), exercising DI without any //! real I/O (README "Domaine/application testés sans I/O"). use std::sync::{Arc, Mutex}; use application::{HealthInput, HealthUseCase}; use domain::events::DomainEvent; use domain::ports::{Clock, EventBus, EventStream, IdGenerator}; use uuid::Uuid; /// A clock that always returns the same configured instant. struct FixedClock(i64); impl Clock for FixedClock { fn now_millis(&self) -> i64 { self.0 } } /// An id generator yielding a deterministic, predefined UUID. struct SeqIdGenerator(Uuid); impl IdGenerator for SeqIdGenerator { fn new_uuid(&self) -> Uuid { self.0 } } /// A spy event bus capturing every published event for assertions. #[derive(Default)] struct SpyEventBus { published: Mutex>, } impl EventBus for SpyEventBus { fn publish(&self, event: DomainEvent) { self.published.lock().unwrap().push(event); } fn subscribe(&self) -> EventStream { Box::new(std::iter::empty()) } } fn fixed_uuid() -> Uuid { Uuid::parse_str("11111111-2222-3333-4444-555555555555").unwrap() } #[test] fn health_report_reflects_injected_ports_and_input() { let clock = Arc::new(FixedClock(1_700_000_000_123)); let ids = Arc::new(SeqIdGenerator(fixed_uuid())); let bus = Arc::new(SpyEventBus::default()); let uc = HealthUseCase::new(clock, ids, Arc::clone(&bus) as Arc); let report = uc .execute(HealthInput { note: Some("ping".to_owned()), }) .expect("health never errs"); assert!(report.alive); assert_eq!(report.time_millis, 1_700_000_000_123); assert_eq!(report.correlation_id, fixed_uuid().to_string()); assert_eq!(report.note.as_deref(), Some("ping")); assert_eq!(report.version, env!("CARGO_PKG_VERSION")); } #[test] fn health_publishes_exactly_one_domain_event() { let clock = Arc::new(FixedClock(0)); let ids = Arc::new(SeqIdGenerator(fixed_uuid())); let bus = Arc::new(SpyEventBus::default()); let uc = HealthUseCase::new(clock, ids, Arc::clone(&bus) as Arc); uc.execute(HealthInput::default()).unwrap(); let published = bus.published.lock().unwrap(); assert_eq!(published.len(), 1, "exactly one smoke event is published"); match &published[0] { DomainEvent::ProjectCreated { project_id } => { // The smoke event reuses the correlation id as the (fake) project id. assert_eq!(project_id.as_uuid(), fixed_uuid()); } other => panic!("expected ProjectCreated smoke event, got {other:?}"), } } #[test] fn health_note_defaults_to_none() { let uc = HealthUseCase::new( Arc::new(FixedClock(42)), Arc::new(SeqIdGenerator(fixed_uuid())), Arc::new(SpyEventBus::default()), ); let report = uc.execute(HealthInput::default()).unwrap(); assert_eq!(report.note, None); }