namespace HrynCo.NotificationService.Services.Tests.EmailProcessing; using HrynCo.NotificationService.Contracts.Messages; using HrynCo.NotificationService.Worker; using Hrynco.RabbitMq; public sealed class SendEmailDeliveryValidatorTests { [Fact] public void ValidItemTrackerDelivery_IsAccepted() { string? error = SendEmailDeliveryValidator.GetValidationError( CreateMessage(), CreateContext(), SendEmailConsumer.SupportedMessageType); Assert.Null(error); } [Fact] public void MissingMessageId_IsRejected() { RabbitMqMessageContext context = CreateContext() with { MessageId = null }; string? error = SendEmailDeliveryValidator.GetValidationError( CreateMessage(), context, SendEmailConsumer.SupportedMessageType); Assert.Equal("AMQP MessageId is required.", error); } [Fact] public void UnsupportedContractVersion_IsRejected() { RabbitMqMessageContext context = CreateContext() with { MessageType = "Notification.SendEmail.v2" }; string? error = SendEmailDeliveryValidator.GetValidationError( CreateMessage(), context, SendEmailConsumer.SupportedMessageType); Assert.Equal("Unsupported AMQP message type 'Notification.SendEmail.v2'.", error); } private static RabbitMqMessageContext CreateContext() => new() { QueueName = SendEmailConsumer.IncomingQueue, Exchange = string.Empty, RoutingKey = SendEmailConsumer.IncomingQueue, MessageId = Guid.NewGuid().ToString("D"), MessageType = SendEmailConsumer.SupportedMessageType, CorrelationId = "correlation-id", ContentType = "application/json" }; private static SendEmailMessage CreateMessage() => new() { CorrelationContext = new CorrelationContext { CorrelationId = "correlation-id", ReplyTo = "item-tracker.notifications.result" }, Data = new SendEmailMessageData { ServiceName = "StoreMate-Prod", TemplateKey = "EmailVerification", RecipientEmail = "owner@example.com", RecipientName = "Owner", LanguageCode = "uk", Variables = new Dictionary { ["AppName"] = "StoreMate" } } }; }