public async Task When_receiving_valid_message_it_should_flow_through_pipeline_normally() { TestMessage receivedMessage = null; Dictionary <string, string> receivedHeaders = null; IValidationFailed <TestMessage> failedMessage = null; var sync = new ManualResetEvent(false); var activator = new BuiltinHandlerActivator(); activator .Handle <TestMessage>((bus, context, message) => { // This should happen. receivedMessage = message; receivedHeaders = context.Message.Headers; sync.Set(); return(Task.CompletedTask); }) .Handle <IValidationFailed <TestMessage> >(failed => { // This should not happen, but signal completion. failedMessage = failed; sync.Set(); return(Task.CompletedTask); }); using (IBus bus = CreateBus(activator, o => o.ValidateIncomingMessages(_validatorFactoryMock.Object))) { // Act var testMessage = new TestMessage { ShouldPassValidation = true }; await bus.Send(testMessage); // Assert sync.WaitOne(Debugger.IsAttached ? -1 : 5000); failedMessage.Should().BeNull(); receivedMessage.Should().NotBeNull(); receivedMessage.IsValidated.Should().BeTrue(); receivedHeaders.Should() .ContainKey(ValidateIncomingStep.ValidatorTypeKey) .WhichValue.Should() .Be(typeof(TestMessageValidator).GetSimpleAssemblyQualifiedName()); } _loggerFactory.LogEvents .Select(le => le.Exception) .Should() .NotContain(ex => ex is MessageCouldNotBeDispatchedToAnyHandlersException); }
public async Task Given_passThrough_is_configured_when_receiving_invalid_message_it_should_be_normally_handled() { string messageId = null; TestMessage receivedMessage = null; var sync = new ManualResetEvent(false); var activator = new BuiltinHandlerActivator(); activator .Handle <TestMessage>((bus, context, message) => { // This should happen. receivedMessage = message; messageId = context.Message.GetMessageId(); sync.Set(); return(Task.CompletedTask); }); using (IBus bus = CreateBus(activator, o => { o.ValidateIncomingMessages(_validatorFactoryMock.Object, v => v.PassThrough <TestMessage>() ); })) { // Act var testMessage = new TestMessage { ShouldPassValidation = false }; await bus.Send(testMessage); // Assert sync.WaitOne(Debugger.IsAttached ? -1 : 5000); receivedMessage.Should().NotBeNull(); receivedMessage.IsValidated.Should().BeTrue(); } _loggerFactory.LogEvents .Select(le => le.Exception) .Should() .NotContain(ex => ex is MessageCouldNotBeDispatchedToAnyHandlersException); _loggerFactory.LogEvents .Select(le => le.ToString()) .Should() .ContainMatch($"Debug: Message \"{messageId}\" failed to validate.*The specified condition was not met for 'Should Pass Validation'.*"); _loggerFactory.LogEvents .Select(le => le.Message) .Should() .ContainMatch("*is configured to pass through."); }
public async Task OnlyDeliversMessagesOfTheCorrectType() { Mock <IMessageDeserializer <TestMessage> > mockTestMessageDeserializer = new Mock <IMessageDeserializer <TestMessage> >(); mockTestMessageDeserializer.Setup(md => md.GetTypeName()) .Returns(typeof(TestMessage).Name); TestMessage testMessage = new TestMessage(); mockTestMessageDeserializer.Setup(md => md.Deserialize(It.IsAny <Stream>())) .Returns(testMessage); BrokeredMessage brokeredMessageThatShouldBeIgnored = new BrokeredMessage() { Properties = { { MessagePropertyNames.TypeName, "SomeMessageTypeThatIDontWant" } } }; BrokeredMessage brokeredMessageThatShouldBeReceived = new BrokeredMessage() { Properties = { { MessagePropertyNames.TypeName, typeof(TestMessage).Name } } }; IObservable <BrokeredMessage> brokeredMessages = Observable.Create <BrokeredMessage>(o => { o.OnNext(brokeredMessageThatShouldBeIgnored); o.OnNext(brokeredMessageThatShouldBeReceived); o.OnCompleted(); return(Disposable.Empty); }); MessageSource <TestMessage> messageSource = new MessageSource <TestMessage>(brokeredMessages, new[] { mockTestMessageDeserializer.Object }, Mock.Of <IMessageBrokeredMessageTable>()); TestMessage message = await messageSource.Messages.SingleOrDefaultAsync(); message.Should().NotBeNull(); // NOTE: Would be great to be able to verify that testBrokeredMessage.CompleteAsync() wasn't called here, but I would have to build abstraction around BrokeredMessage for that because it can't be mocked (since it's sealed) mockTestMessageDeserializer.Verify(md => md.Deserialize(It.IsAny <Stream>()), Times.Once()); }
public async Task Given_deadLetter_is_configured_when_receiving_invalid_message_it_should_be_moved_to_error_queue() { string messageId = null; TestMessage receivedMessage = null; var sync = new ManualResetEvent(false); var inMemNetwork = new InMemNetwork(); var activator = new BuiltinHandlerActivator(); activator .Handle <TestMessage>(message => { // This should not happen, but signal completion. receivedMessage = message; sync.Set(); return(Task.CompletedTask); }); using (IBus bus = CreateBus(activator, o => { o.ValidateIncomingMessages(_validatorFactoryMock.Object, v => v.DeadLetter <TestMessage>() ); o.OnPipelineCompletion <TestMessage>(failed => { messageId = MessageContext.Current.Message.GetMessageId(); sync.Set(); }); }, inMemNetwork)) { // Act var testMessage = new TestMessage { ShouldPassValidation = false }; await bus.Send(testMessage); // Assert sync.WaitOne(Debugger.IsAttached ? -1 : 5000); receivedMessage.Should().BeNull(); var errorQueueMessages = inMemNetwork.GetMessages(ErrorQueueName).ToList(); InMemTransportMessage message = errorQueueMessages.Should() .HaveCount(1) .And.Subject.Single(); message.Headers.Should() .ContainKey(Headers.ErrorDetails) .WhichValue.Should() .Match($"*{nameof(TestMessage.ShouldPassValidation)}: The specified condition was not met*"); message.Headers.Should() .ContainKey(Headers.Type) .WhichValue.Should() .StartWith(typeof(TestMessage).FullName); } _loggerFactory.LogEvents .Select(le => le.Exception) .Should() .NotContain(ex => ex is MessageCouldNotBeDispatchedToAnyHandlersException); _loggerFactory.LogEvents .Select(le => le.ToString()) .Should() .ContainMatch($"Debug: Message \"{messageId}\" failed to validate.*The specified condition was not met for 'Should Pass Validation'.*"); _loggerFactory.LogEvents .Select(le => le.Message) .Should() .ContainMatch("*is configured to be moved to error queue.") .And .ContainMatch("Moving message with ID *"); }
public async Task When_receiving_invalid_message_it_should_be_wrapped_as_invalid_message() { string messageId = null; TestMessage receivedMessage = null; IValidationFailed <TestMessage> failedMessage = null; var sync = new ManualResetEvent(false); var activator = new BuiltinHandlerActivator(); activator .Handle <TestMessage>(message => { // This should not happen, but signal completion. receivedMessage = message; sync.Set(); return(Task.CompletedTask); }) .Handle <IValidationFailed <TestMessage> >((bus, context, failed) => { // This should happen. failedMessage = failed; messageId = context.Message.GetMessageId(); sync.Set(); return(Task.CompletedTask); }); using (IBus bus = CreateBus(activator, o => o.ValidateIncomingMessages(_validatorFactoryMock.Object))) { // Act var testMessage = new TestMessage { ShouldPassValidation = false }; await bus.Send(testMessage); // Assert sync.WaitOne(Debugger.IsAttached ? -1 : 5000); receivedMessage.Should().BeNull(); failedMessage.Should().NotBeNull(); failedMessage.ValidationResult.Should().NotBeNull(); failedMessage.Headers.Should() .NotBeNull() .And.NotBeEmpty() .And.ContainKey(ValidateIncomingStep.ValidatorTypeKey) .WhichValue.Should() .Be(typeof(TestMessageValidator).GetSimpleAssemblyQualifiedName()); failedMessage.Message.IsValidated.Should().BeTrue(); failedMessage.ValidatorType.Should().Be <TestMessageValidator>(); } _loggerFactory.LogEvents .Select(le => le.Exception) .Should() .NotContain(ex => ex is MessageCouldNotBeDispatchedToAnyHandlersException); _loggerFactory.LogEvents .Select(le => le.ToString()) .Should() .ContainMatch($"Debug: Message \"{messageId}\" failed to validate.*The specified condition was not met for 'Should Pass Validation'.*"); _loggerFactory.LogEvents .Select(le => le.Message) .Should() .ContainMatch("*is configured to be wrapped as *"); }