protected void TestInboxDeferred(string queueUriFormat) { var configuration = GetConfiguration(queueUriFormat, 1, false); var module = new InboxDeferredModule(); configuration.Modules.Add(module); Guid messageId; var messageType = typeof (ReceivePipelineCommand).FullName; using (var bus = new ServiceBus(configuration)) { bus.Start(); var transportMessage = bus.Send(new ReceivePipelineCommand(), c => c.Defer(DateTime.Now.AddMilliseconds(500)) .WithRecipient(configuration.Inbox.WorkQueue)); var timeout = DateTime.Now.AddMilliseconds(1000); Assert.IsNotNull(transportMessage); messageId = transportMessage.MessageId; while (module.TransportMessage == null && DateTime.Now < timeout) { Thread.Sleep(5); } } Assert.IsNotNull(module.TransportMessage); Assert.True(messageId.Equals(module.TransportMessage.MessageId)); Assert.True(messageType.Equals(module.TransportMessage.MessageType, StringComparison.OrdinalIgnoreCase)); }
protected void TestDeferredProcessing(string queueUriFormat, bool isTransactional) { const int deferredMessageCount = 10; const int millisecondsToDefer = 500; var configuration = GetInboxConfiguration(queueUriFormat, 1, isTransactional); var module = new DeferredMessageModule(deferredMessageCount); configuration.Modules.Add(module); using (var bus = new ServiceBus(configuration)) { bus.Start(); var ignoreTillDate = DateTime.Now.AddSeconds(5); for (var i = 0; i < deferredMessageCount; i++) { EnqueueDeferredMessage(bus, ignoreTillDate); ignoreTillDate = ignoreTillDate.AddMilliseconds(millisecondsToDefer); } // add the extra time else there is no time to process message being returned var timeout = ignoreTillDate.AddSeconds(150); var timedOut = false; _log.Information(string.Format("[start wait] : now = '{0}'", DateTime.Now)); // wait for the message to be returned from the deferred queue while (!module.AllMessagesHandled() && !timedOut) { Thread.Sleep(millisecondsToDefer); timedOut = timeout < DateTime.Now; } _log.Information(string.Format("[end wait] : now = '{0}' / timeout = '{1}' / timed out = '{2}'", DateTime.Now, timeout, timedOut)); _log.Information(string.Format("{0} of {1} deferred messages returned to the inbox.", module.NumberOfDeferredMessagesReturned, deferredMessageCount)); _log.Information(string.Format("{0} of {1} deferred messages handled.", module.NumberOfMessagesHandled, deferredMessageCount)); Assert.IsTrue(module.AllMessagesHandled(), "All the deferred messages were not handled."); Assert.IsTrue(configuration.Inbox.ErrorQueue.IsEmpty()); Assert.IsNull(configuration.Inbox.DeferredQueue.GetMessage()); Assert.IsNull(configuration.Inbox.WorkQueue.GetMessage()); } AttemptDropQueues(queueUriFormat); }
protected void TestInboxConcurrency(string workQueueUriFormat, string errorQueueUriFormat, int msToComplete, bool isTransactional) { const int threadCount = 1; var padlock = new object(); var configuration = GetConfiguration(workQueueUriFormat, errorQueueUriFormat, threadCount, isTransactional); var module = new InboxConcurrencyModule(); configuration.Modules.Add(module); using (var bus = new ServiceBus(configuration)) { for (var i = 0; i < threadCount; i++) { var message = bus.CreateTransportMessage(new ConcurrentCommand { MessageIndex = i }); configuration.Inbox.WorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); } var idleThreads = new List<int>(); bus.Events.ThreadWaiting += (sender, args) => { lock (padlock) { if (idleThreads.Contains(Thread.CurrentThread.ManagedThreadId)) { return; } idleThreads.Add(Thread.CurrentThread.ManagedThreadId); } }; bus.Start(); while (idleThreads.Count < threadCount) { Thread.Sleep(30); } } AttemptDropQueues(workQueueUriFormat, errorQueueUriFormat); Assert.AreEqual(threadCount, module.OnAfterGetMessageCount, string.Format("Got {0} messages but {1} were sent.", module.OnAfterGetMessageCount, threadCount)); Assert.IsTrue(module.AllMessagesReceivedWithinTimespan(msToComplete), "All dequeued messages have to be within {0} ms of first get message.", msToComplete); }
public void Should_be_able_to_roll_back_any_database_and_queue_changes_when_an_exception_occurs_in_the_receive_pipeline() { var configuration = DefaultConfiguration(); var inboxWorkQueue = configuration.QueueManager.GetQueue("msmq://./test-inbox-work"); var inboxJournalQueue = configuration.QueueManager.GetQueue("msmq://./test-inbox-journal"); var inboxErrorQueue = configuration.QueueManager.GetQueue("msmq://./test-error"); configuration.Inbox = new InboxQueueConfiguration { WorkQueue = inboxWorkQueue, JournalQueue = inboxJournalQueue, ErrorQueue = inboxErrorQueue, DurationToSleepWhenIdle = new[] {TimeSpan.FromMilliseconds(5)}, DurationToIgnoreOnFailure = new[] {TimeSpan.FromMilliseconds(5)}, MaximumFailureCount = 100, ThreadCount = 1 }; configuration.QueueManager.CreatePhysicalQueues(configuration, QueueCreationType.All); inboxWorkQueue.Purge(); inboxJournalQueue.Purge(); inboxErrorQueue.Purge(); var module = new ReceivePipelineExceptionModule(inboxWorkQueue); configuration.Modules.Add(module); using (var bus = new ServiceBus(configuration)) { var message = bus.CreateTransportMessage(new ReceivePipelineCommand()); inboxWorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); Assert.AreEqual(1, inboxWorkQueue.Count()); bus.Start(); while (module.ShouldWait()) { Thread.Sleep(10); } } }
protected void TestExceptionHandling(string workQueueUriFormat, string errorQueueUriFormat) { var configuration = DefaultConfiguration(true); var inboxWorkQueue = configuration.QueueManager.GetQueue(string.Format(workQueueUriFormat, "test-inbox-work")); var inboxErrorQueue = configuration.QueueManager.GetQueue(string.Format(errorQueueUriFormat, "test-error")); configuration.Inbox = new InboxQueueConfiguration { WorkQueue = inboxWorkQueue, ErrorQueue = inboxErrorQueue, DurationToSleepWhenIdle = new[] { TimeSpan.FromMilliseconds(5) }, DurationToIgnoreOnFailure = new[] { TimeSpan.FromMilliseconds(5) }, MaximumFailureCount = 100, ThreadCount = 1 }; inboxWorkQueue.Drop(); inboxErrorQueue.Drop(); configuration.QueueManager.CreatePhysicalQueues(configuration); var module = new ReceivePipelineExceptionModule(inboxWorkQueue); configuration.Modules.Add(module); using (var bus = new ServiceBus(configuration)) { var message = bus.CreateTransportMessage(new ReceivePipelineCommand()); inboxWorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); Assert.IsFalse(inboxWorkQueue.IsEmpty()); bus.Start(); while (module.ShouldWait()) { Thread.Sleep(10); } } }
private const int MillisecondsToDefer = 1000; // give the service bus enough time to start up #endregion Fields #region Methods protected void TestDeferredProcessing(string workQueueUriFormat, string deferredQueueUriFormat, string errorQueueUriFormat, bool isTransactional) { var configuration = GetInboxConfiguration(workQueueUriFormat, deferredQueueUriFormat, errorQueueUriFormat, 1, isTransactional); var module = new DeferredMessageModule(); configuration.Modules.Add(module); using (var bus = new ServiceBus(configuration)) { bus.Start(); var message = bus.CreateTransportMessage(new SimpleCommand()); message.IgnoreTillDate = DateTime.Now.AddMilliseconds(MillisecondsToDefer); message.RecipientInboxWorkQueueUri = configuration.Inbox.WorkQueue.Uri.ToString(); configuration.Inbox.WorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); var timeout = DateTime.Now.AddMilliseconds(MillisecondsToDefer + 5000); // wait for the message to be returned from the deferred queue while ((!module.DeferredMessageReturned || !module.MessageHandled) && timeout > DateTime.Now) { Thread.Sleep(5); } Assert.IsTrue(module.DeferredMessageReturned, "Deferred message was never returned."); Assert.IsTrue(module.MessageHandled, "Deferred message was never handled."); Assert.IsTrue(configuration.Inbox.ErrorQueue.IsEmpty()); Assert.IsNull(configuration.Inbox.DeferredQueue.GetMessage()); Assert.IsNull(configuration.Inbox.WorkQueue.GetMessage()); } AttemptDropQueues(workQueueUriFormat, errorQueueUriFormat); }
public void Should_be_able_to_send_a_message_to_a_routed_queue() { var command = new SimpleCommand { Name = Guid.NewGuid().ToString() }; var configuration = CreateMemoryConfiguration(); var module = new ServiceBusRoutingModule(); configuration.Modules.Add(module); var mockMessageRouteProvider = new Mock<IMessageRouteProvider>(); mockMessageRouteProvider.Setup(mock => mock.GetRouteUris(It.IsAny<object>())).Returns(new List<string> { configuration.Inbox.WorkQueue.Uri.ToString() }); configuration.MessageRouteProvider = mockMessageRouteProvider.Object; using (var bus = new ServiceBus(configuration)) { bus.Start(); bus.Send(command); var timeout = DateTime.Now.AddMilliseconds(5000); while (DateTime.Now < timeout && module.SimpleCommand == null) { Thread.Sleep(50); } Assert.IsNotNull(module.SimpleCommand); Assert.AreEqual(command.Name, module.SimpleCommand.Name); } }
public void Should_be_able_to_send_a_message_to_a_routed_queue() { var command = new SimpleCommand { Name = Guid.NewGuid().ToString() }; var configuration = CreateMemoryConfiguration(); var mockMessageRouteProvider = Mock<IMessageRouteProvider>(); mockMessageRouteProvider.Stub(mock => mock.GetRouteUris(Arg<object>.Is.Anything)).Return(new List<string> { configuration.Inbox.WorkQueue.Uri.ToString() }); configuration.MessageRouteProvider = mockMessageRouteProvider; using (var bus = new ServiceBus(configuration)) { bus.Configuration.Modules.Add(new MockModule(this)); bus.Start(); bus.Send(command); var waitTill = DateTime.Now.AddMilliseconds(15000); while (DateTime.Now < waitTill && TransportMessage == null) { Thread.Sleep(50); } Assert.IsNotNull(TransportMessage); Assert.AreEqual(command.Name, ((SimpleCommand)bus.Configuration.Serializer.Deserialize(typeof(SimpleCommand), new MemoryStream(TransportMessage.Message))).Name); } }
public void Should_be_able_to_publish_an_event() { var mockSubscriptionManager = new Mock<ISubscriptionManager>(); const string SUBSCRIBER1_URI = "memory://./subscriber1"; const string SUBSCRIBER2_URI = "memory://./subscriber2"; var subscribers = new List<string> { SUBSCRIBER1_URI, SUBSCRIBER2_URI }; mockSubscriptionManager.Setup(mock => mock.GetSubscribedUris(It.IsAny<object>())).Returns(subscribers); var configuration = CreateMemoryConfiguration(); configuration.SubscriptionManager = mockSubscriptionManager.Object; var subscriber1 = configuration.QueueManager.CreateQueue(SUBSCRIBER1_URI); var subscriber2 = configuration.QueueManager.CreateQueue(SUBSCRIBER2_URI); ; using (var bus = new ServiceBus(configuration).Start()) { const string EVENT_NAME = "test::event"; bus.Publish(new SimpleEvent { EventName = EVENT_NAME }); } Assert.NotNull(subscriber1.GetMessage()); Assert.IsNull(subscriber1.GetMessage()); Assert.NotNull(subscriber2.GetMessage()); Assert.IsNull(subscriber2.GetMessage()); }
protected void TestInboxThroughput(string workQueueUriFormat, string errorQueueUriFormat, int timeoutMilliseconds, int count, bool isTransactional) { const int threadCount = 1; var padlock = new object(); var configuration = GetConfiguration(workQueueUriFormat, errorQueueUriFormat, threadCount, isTransactional); Console.WriteLine("Sending {0} messages to input queue '{1}'.", count, configuration.Inbox.WorkQueue.Uri); var sw = new Stopwatch(); using (var bus = new ServiceBus(configuration)) { for (var i = 0; i < 5; i++) { var warmup = bus.CreateTransportMessage(new SimpleCommand("warmup")); configuration.Inbox.WorkQueue.Enqueue(warmup.MessageId, configuration.Serializer.Serialize(warmup)); } var idleThreads = new List<int>(); bus.Events.ThreadWaiting += (sender, args) => { lock (padlock) { if (idleThreads.Contains(Thread.CurrentThread.ManagedThreadId)) { return; } idleThreads.Add(Thread.CurrentThread.ManagedThreadId); } }; bus.Start(); while (idleThreads.Count < threadCount) { Thread.Sleep(25); } bus.Stop(); sw.Start(); for (var i = 0; i < count; i++) { var message = bus.CreateTransportMessage(new SimpleCommand("command " + i)); configuration.Inbox.WorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); } sw.Stop(); Console.WriteLine("Took {0} ms to send {1} messages. Starting processing.", sw.ElapsedMilliseconds, count); idleThreads.Clear(); bus.Start(); sw.Reset(); sw.Start(); while (idleThreads.Count < threadCount) { Thread.Sleep(25); } sw.Stop(); } AttemptDropQueues(workQueueUriFormat, errorQueueUriFormat); var ms = sw.ElapsedMilliseconds; Console.WriteLine("Processed {0} messages in {1} ms", count, ms); Assert.IsTrue(ms < timeoutMilliseconds, "Should be able to process at least {0} messages in {1} ms but it ook {2} ms.", count, timeoutMilliseconds, ms); }
protected void TestInboxError(string workQueueUriFormat, string errorQueueUriFormat, bool isTransactional) { var padlock = new object(); var configuration = GetConfiguration(workQueueUriFormat, errorQueueUriFormat, 1, isTransactional); using (var bus = new ServiceBus(configuration)) { var message = bus.CreateTransportMessage(new NoHandlerCommand()); configuration.Inbox.WorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); var idleThreads = new List<int>(); bus.Events.ThreadWaiting += (sender, args) => { lock (padlock) { if (idleThreads.Contains(Thread.CurrentThread.ManagedThreadId)) { return; } idleThreads.Add(Thread.CurrentThread.ManagedThreadId); } }; bus.Start(); while (idleThreads.Count < 1) { Thread.Sleep(5); } Assert.NotNull(configuration.Inbox.ErrorQueue.GetMessage()); } AttemptDropQueues(workQueueUriFormat, errorQueueUriFormat); }
protected void TestIdempotenceProcessing(string workQueueUriFormat, string errorQueueUriFormat, bool isTransactional, bool enqueueUniqueMessages) { const int messageCount = 200; var configuration = GetInboxConfiguration(workQueueUriFormat, errorQueueUriFormat, 5, isTransactional); var padlock = new object(); using (var bus = new ServiceBus(configuration)) { if (enqueueUniqueMessages) { for (int i = 0; i < messageCount; i++) { var message = bus.CreateTransportMessage(new IdempotenceCommand()); message.RecipientInboxWorkQueueUri = configuration.Inbox.WorkQueue.Uri.ToString(); configuration.Inbox.WorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); } } else { var message = bus.CreateTransportMessage(new IdempotenceCommand()); message.RecipientInboxWorkQueueUri = configuration.Inbox.WorkQueue.Uri.ToString(); for (int i = 0; i < messageCount; i++) { configuration.Inbox.WorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); } } var idleThreads = new List<int>(); bus.Events.ThreadWaiting += (sender, args) => { lock (padlock) { if (idleThreads.Contains(Thread.CurrentThread.ManagedThreadId)) { return; } idleThreads.Add(Thread.CurrentThread.ManagedThreadId); } }; bus.Start(); while (idleThreads.Count < 5) { Thread.Sleep(5); } Assert.IsNull(configuration.Inbox.ErrorQueue.GetMessage()); Assert.IsNull(configuration.Inbox.WorkQueue.GetMessage()); if (enqueueUniqueMessages) { Assert.AreEqual(messageCount, ((IdempotenceMessageHandlerFactory)bus.Configuration.MessageHandlerFactory).ProcessedCount); } else { Assert.AreEqual(1, ((IdempotenceMessageHandlerFactory)bus.Configuration.MessageHandlerFactory).ProcessedCount); } } AttemptDropQueues(workQueueUriFormat, errorQueueUriFormat); }
protected void TestOutboxSending(string workQueueUriFormat, string errorQueueUriFormat, bool isTransactional) { const int count = 100; const int threadCount = 3; var padlock = new object(); var configuration = GetConfiguration(workQueueUriFormat, errorQueueUriFormat, threadCount, isTransactional); var messageRouteProvider = new Mock<IMessageRouteProvider>(); var receiverWorkQueueUri = string.Format(workQueueUriFormat, "test-receiver-work"); messageRouteProvider.Setup(m => m.GetRouteUris(It.IsAny<string>())).Returns(new[] {receiverWorkQueueUri}); configuration.MessageRouteProvider = messageRouteProvider.Object; Console.WriteLine("Sending {0} messages.", count); using (var bus = new ServiceBus(configuration)) { for (var i = 0; i < count; i++) { bus.Send(new SimpleCommand()); } var idleThreads = new List<int>(); bus.Events.ThreadWaiting += (sender, args) => { if (!args.PipelineType.FullName.Equals(typeof (OutboxPipeline).FullName)) { return; } lock (padlock) { if (idleThreads.Contains(Thread.CurrentThread.ManagedThreadId)) { return; } idleThreads.Add(Thread.CurrentThread.ManagedThreadId); } }; bus.Start(); while (idleThreads.Count < threadCount) { Thread.Sleep(25); } } using (var queueManager = QueueManager.Default()) { var receiverWorkQueue = queueManager.GetQueue(receiverWorkQueueUri); for (var i = 0; i < count; i++) { var receivedMessage = receiverWorkQueue.GetMessage(); Assert.IsNotNull(receivedMessage); receiverWorkQueue.Acknowledge(receivedMessage.AcknowledgementToken); } receiverWorkQueue.AttemptDrop(); var outboxWorkQueue = queueManager.GetQueue(string.Format(workQueueUriFormat, "test-outbox-work")); Assert.IsTrue(outboxWorkQueue.IsEmpty()); outboxWorkQueue.AttemptDrop(); queueManager.GetQueue(string.Format(errorQueueUriFormat, "test-error")).AttemptDrop(); } }
protected void TestInboxConcurrency(string queueSchemeAndHost, bool useJournal, int msToComplete) { const int COUNT = 10; var padlock = new object(); var configuration = GetTestInboxConfiguration(queueSchemeAndHost, useJournal, COUNT); var afterDequeueDate = new List<DateTime>(); var offsetDate = DateTime.MinValue; using (var bus = new ServiceBus(configuration)) { for (var i = 0; i < COUNT; i++) { var message = bus.CreateTransportMessage(new ConcurrentCommand { MessageIndex = i }); configuration.Inbox.WorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); } var idleCount = 0; bus.Events.ThreadWaiting += (sender, args) => { lock (padlock) { idleCount++; } }; bus.Events.AfterDequeueStream += (sender, args) => { lock (padlock) { if (offsetDate == DateTime.MinValue) { offsetDate = DateTime.Now; Console.WriteLine("Offset date: {0}", offsetDate.ToString("yyyy-MM-dd HH:mm:ss.fff")); } var dateTime = DateTime.Now; afterDequeueDate.Add(dateTime); Console.WriteLine("Dequeued date: {0}", dateTime.ToString("yyyy-MM-dd HH:mm:ss.fff")); } }; bus.Start(); while (idleCount < COUNT) { Thread.Sleep(50); } } Assert.AreEqual(COUNT, afterDequeueDate.Count, string.Format("Dequeued {0} messages but {1} were sent.", afterDequeueDate.Count, COUNT)); foreach (var dateTime in afterDequeueDate) { Assert.IsTrue(dateTime.Subtract(offsetDate) < TimeSpan.FromMilliseconds(msToComplete), "All dequeued messages have to be within {0} ms of first dequeue.", msToComplete); } }
protected void TestInboxThroughput(string queueSchemeAndHost, int count, int timeoutMilliseconds, bool useJournal) { var configuration = GetTestInboxConfiguration(queueSchemeAndHost, useJournal, 1); Console.WriteLine("Sending {0} messages to input queue '{1}'.", count, configuration.Inbox.WorkQueue.Uri); var sw = new Stopwatch(); using (var bus = new ServiceBus(configuration)) { for (var i = 0; i < 5; i++) { var warmup = bus.CreateTransportMessage(new SimpleCommand("warmup")); configuration.Inbox.WorkQueue.Enqueue(warmup.MessageId, configuration.Serializer.Serialize(warmup)); } var working = true; bus.Events.ThreadWaiting += (sender, args) => { working = false; }; bus.Start(); while (working) { Thread.Sleep(25); } bus.Stop(); sw.Start(); for (var i = 0; i < count; i++) { var message = bus.CreateTransportMessage(new SimpleCommand("command " + i)); configuration.Inbox.WorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); } sw.Stop(); Console.WriteLine("Took {0} ms to send {1} messages. Starting processing.", sw.ElapsedMilliseconds, count); bus.Start(); sw.Reset(); sw.Start(); working = true; while (working) { Thread.Sleep(25); } sw.Stop(); } var ms = sw.ElapsedMilliseconds; Console.WriteLine("Processed {0} messages in {1} ms", count, ms); Assert.IsTrue(ms < timeoutMilliseconds, "Should be able to process at least {0} messages in {1} ms but it ook {2} ms.", count, timeoutMilliseconds, ms); }
public void TestResourceUsage(string queueUriFormat, bool isTransactional) { const int threadCount = 5; var configuration = GetConfiguration(queueUriFormat, isTransactional, threadCount); var cpuCounter = new PerformanceCounterValue(new PerformanceCounter { CategoryName = "Processor", CounterName = "% Processor Time", InstanceName = "_Total" }); var padlock = new object(); var idleThreads = new List<int>(); var startDate = DateTime.Now; var endDate = startDate.AddSeconds(10); var iteration = 0; float cpuUsageLimit; float cpuMaximumUsage = 0f; cpuCounter.NextValue(); Thread.Sleep(1000); cpuUsageLimit = cpuCounter.NextValue() + 25F; using (var bus = new ServiceBus(configuration).Start()) { bus.Events.ThreadWaiting += (sender, args) => { lock (padlock) { if (idleThreads.Contains(Thread.CurrentThread.ManagedThreadId)) { return; } idleThreads.Add(Thread.CurrentThread.ManagedThreadId); } }; while (DateTime.Now < endDate) { iteration++; for (var i = 0; i < 5; i++) { var message = bus.CreateTransportMessage(new SimpleCommand("[resource testing]"), c => c.WithRecipient(configuration.Inbox.WorkQueue)); configuration.Inbox.WorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); } idleThreads.Clear(); Console.WriteLine("[checking usage] : iteration = {0}", iteration); while (idleThreads.Count < threadCount) { var cpuUsage = cpuCounter.NextValue(); if (cpuUsage > cpuMaximumUsage) { cpuMaximumUsage = cpuUsage; } Assert.IsTrue(cpuUsage < cpuUsageLimit, string.Format("[EXCEEDED] : cpu usage = {0} / limit = {1}", cpuUsage, cpuUsageLimit)); Thread.Sleep(25); } } Console.WriteLine("[done] : started = '{0}' / end = '{1}'", startDate, endDate); Console.WriteLine("[CPU] : maximum usage = {0} / cpu usage limit = {1}", cpuMaximumUsage, cpuUsageLimit); } }
protected void TestInboxError(string queueSchemeAndHost, bool useJournal) { var configuration = GetTestInboxConfiguration(queueSchemeAndHost, useJournal, 1); using (var bus = new ServiceBus(configuration)) { var message = bus.CreateTransportMessage(new NoHandlerCommand()); configuration.Inbox.WorkQueue.Enqueue(message.MessageId, configuration.Serializer.Serialize(message)); var working = true; bus.Events.ThreadWaiting += (sender, args) => { working = false; }; bus.Start(); while (working) { Thread.Sleep(5); } } Assert.NotNull(configuration.Inbox.ErrorQueue.Dequeue()); }