public void WhenMessageFailsThenOnMessageFaultIsCalled() { // arrange var onMessageFaultMock = new Mock <Action <AbstractConsumerSettings, object, Exception> >(); var consumerSettings = new ConsumerSettings { Instances = 1, Topic = "topic1", ConsumerMode = ConsumerMode.Consumer, ConsumerType = typeof(IConsumer <SomeMessage>), MessageType = typeof(SomeMessage), OnMessageFault = onMessageFaultMock.Object }; var p = new ConsumerInstancePool <SomeMessage>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>()); var message = new SomeMessage(); _busMock.SerializerMock.Setup(x => x.Deserialize(typeof(SomeMessage), It.IsAny <byte[]>())).Returns(message); var ex = new Exception("Something went bad"); _busMock.ConsumerMock.Setup(x => x.OnHandle(message, consumerSettings.Topic)) .Returns(Task.FromException <SomeResponse>(ex)); // act p.ProcessMessage(message).Wait(); // assert _busMock.ConsumerMock.Verify(x => x.OnHandle(message, consumerSettings.Topic), Times.Once); // handler called once onMessageFaultMock.Verify(x => x(consumerSettings, message, ex), Times.Once); // callback called once }
public void WhenRequestExpiredThenOnMessageExpiredIsCalled() { // arrange var onMessageExpiredMock = new Mock <Action <AbstractConsumerSettings, object> >(); var consumerSettings = new ConsumerSettings { Instances = 1, Topic = "topic1", ConsumerMode = ConsumerMode.RequestResponse, ConsumerType = typeof(IRequestHandler <SomeRequest, SomeResponse>), MessageType = typeof(SomeRequest), OnMessageExpired = onMessageExpiredMock.Object }; var p = new ConsumerInstancePool <SomeRequest>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>()); var request = new SomeRequest(); var requestMessage = new MessageWithHeaders(); requestMessage.SetHeader(ReqRespMessageHeaders.Expires, _busMock.CurrentTime.AddSeconds(-10)); _busMock.BusMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestMessage)) .Returns(request); // act p.ProcessMessage(request).Wait(); // assert _busMock.HandlerMock.Verify(x => x.OnHandle(It.IsAny <SomeRequest>(), It.IsAny <string>()), Times.Never); // the handler should not be called onMessageExpiredMock.Verify(x => x(consumerSettings, request), Times.Once); // callback called once }
public void WhenRequestExpired_OnMessageExpired_IsCalled() { // arrange var onMessageExpiredMock = new Mock <Action <ConsumerSettings, object> >(); var consumerSettings = new ConsumerSettings { Instances = 1, Topic = "topic1", ConsumerMode = ConsumerMode.RequestResponse, ConsumerType = typeof(IRequestHandler <SomeRequest, SomeResponse>), MessageType = typeof(SomeRequest), OnMessageExpired = onMessageExpiredMock.Object }; var p = new ConsumerInstancePool <SomeRequest>(consumerSettings, _busMock.Object, x => new byte[0], null); var request = new SomeRequest(); string requestId; string replyTo; DateTimeOffset?expires = _busMock.CurrentTime.AddSeconds(-10); _busMock.BusMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestId, out replyTo, out expires)).Returns(request); // act p.ProcessMessage(request).Wait(); // assert _busMock.HandlerMock.Verify(x => x.OnHandle(It.IsAny <SomeRequest>(), It.IsAny <string>()), Times.Never); // the handler should not be called onMessageExpiredMock.Verify(x => x(consumerSettings, request), Times.Once); // callback called once }
public void WhenRequestFailsThenOnMessageFaultIsCalledAndErrorResponseIsSent() { // arrange var onMessageFaultMock = new Mock <Action <AbstractConsumerSettings, object, Exception> >(); var consumerSettings = new ConsumerSettings { Instances = 1, Topic = "topic1", ConsumerMode = ConsumerMode.RequestResponse, ConsumerType = typeof(IRequestHandler <SomeRequest, SomeResponse>), MessageType = typeof(SomeRequest), OnMessageFault = onMessageFaultMock.Object }; var p = new ConsumerInstancePool <SomeRequest>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>()); var request = new SomeRequest(); var requestMessage = new MessageWithHeaders(); var replyTo = "reply-topic"; var requestId = "request-id"; requestMessage.SetHeader(ReqRespMessageHeaders.RequestId, requestId); requestMessage.SetHeader(ReqRespMessageHeaders.ReplyTo, replyTo); _busMock.BusMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestMessage)) .Returns(request); var ex = new Exception("Something went bad"); _busMock.HandlerMock.Setup(x => x.OnHandle(request, consumerSettings.Topic)) .Returns(Task.FromException <SomeResponse>(ex)); // act p.ProcessMessage(request).Wait(); // assert _busMock.HandlerMock.Verify(x => x.OnHandle(request, consumerSettings.Topic), Times.Once); // handler called once onMessageFaultMock.Verify( x => x(consumerSettings, request, ex), Times.Once); // callback called once _busMock.BusMock.Verify( x => x.ProduceResponse(request, requestMessage, It.IsAny <SomeResponse>(), It.Is <MessageWithHeaders>(m => m.Headers[ReqRespMessageHeaders.RequestId] == requestId), It.IsAny <ConsumerSettings>())); }
public void WhenRequestFails_OnMessageFault_IsCalled_And_ErrorResponse_IsSent() { // arrange var onMessageFaultMock = new Mock <Action <ConsumerSettings, object, Exception> >(); var consumerSettings = new ConsumerSettings { Instances = 1, Topic = "topic1", ConsumerMode = ConsumerMode.RequestResponse, ConsumerType = typeof(IRequestHandler <SomeRequest, SomeResponse>), MessageType = typeof(SomeRequest), OnMessageFault = onMessageFaultMock.Object }; var p = new ConsumerInstancePool <SomeRequest>(consumerSettings, _busMock.Object, x => new byte[0]); var request = new SomeRequest(); string requestId; string replyTo = "reply-topic"; DateTimeOffset?expires; _busMock.BusMock.Setup(x => x.DeserializeRequest(typeof(SomeRequest), It.IsAny <byte[]>(), out requestId, out replyTo, out expires)).Returns(request); var ex = new Exception("Something went bad"); _busMock.HandlerMock.Setup(x => x.OnHandle(request, consumerSettings.Topic)).Returns(Task.FromException <SomeResponse>(ex)); // act p.ProcessMessage(request).Wait(); // assert _busMock.HandlerMock.Verify(x => x.OnHandle(request, consumerSettings.Topic), Times.Once); // handler called once onMessageFaultMock.Verify(x => x(consumerSettings, request, ex), Times.Once); // callback called once _busMock.BusMock.Verify(x => x.PublishToTransport(typeof(SomeResponse), It.IsAny <SomeResponse>(), replyTo, It.IsAny <byte[]>())); }
public void WhenNInstancesConfiguredThenExactlyNConsumerInstancesAreWorking() { const int consumerTime = 500; const int consumerInstances = 8; const int messageCount = 500; // arrange var consumerSettings = new ConsumerSettings { Instances = consumerInstances, ConsumerMode = ConsumerMode.Consumer, ConsumerType = typeof(IConsumer <SomeMessage>), MessageType = typeof(SomeMessage) }; var activeInstances = 0; var processedMessageCount = 0; var maxInstances = 0; var maxInstancesLock = new object(); _busMock.ConsumerMock.Setup(x => x.OnHandle(It.IsAny <SomeMessage>(), It.IsAny <string>())) .Returns((SomeMessage msg, string topic) => { Interlocked.Increment(ref activeInstances); lock (maxInstancesLock) { // capture maximum active maxInstances = Math.Max(maxInstances, activeInstances); } return(Task .Delay(consumerTime) .ContinueWith(t => { Interlocked.Decrement(ref activeInstances); Interlocked.Increment(ref processedMessageCount); }, TaskScheduler.Current)); }); var p = new ConsumerInstancePool <SomeMessage>(consumerSettings, _busMock.Bus, x => Array.Empty <byte>()); // act var time = Stopwatch.StartNew(); var tasks = new Task[messageCount]; for (var i = 0; i < messageCount; i++) { tasks[i] = p.ProcessMessage(new SomeMessage()); } Task.WaitAll(tasks); time.Stop(); // assert var minPossibleTime = messageCount * consumerTime / consumerSettings.Instances; var maxPossibleTime = messageCount * consumerTime; processedMessageCount.Should().Be(messageCount); maxInstances.Should().Be(consumerSettings.Instances); // max concurrent consumers should reach number of desired instances time.ElapsedMilliseconds.Should().BeInRange(minPossibleTime, maxPossibleTime); var percent = Math.Round(100f * (time.ElapsedMilliseconds - minPossibleTime) / (maxPossibleTime - minPossibleTime), 2); Log.InfoFormat(CultureInfo.InvariantCulture, "The execution time was {0}% away from the best possible time", percent); // smallest number is better }