示例#1
0
        public async Task ConsumePublish_WithNoError_Test()
        {
            var deliveryTag = (ulong)new Random().Next();

            var consumeAbortedCalled = false;

            var consumer = new RabbitConsumer(_connection, _serviceName, _topicName, MessageHandler, () =>
            {
                consumeAbortedCalled = true;
            }, false, 100, _options, _logger);

            await consumer.StartConsumeAsync(_cancellationTokenSource.Token);


            await _basicConsumer.HandleBasicDeliver(_consumerTag, deliveryTag, false, "exchange", "routingKey", null, null);

            A.CallTo(() => _rabbitChannel.BasicCancel(_consumerTag))
            .MustNotHaveHappened();
            A.CallTo(() => _rabbitChannel.BasicNack(deliveryTag, false, true))
            .MustNotHaveHappened();
            A.CallTo(() => _rabbitChannel.BasicAck(deliveryTag, false))
            .MustHaveHappenedOnceExactly();
            A.CallTo(() =>
                     _rabbitChannel.BasicPublish("", A <string> .Ignored, A <bool> .Ignored,
                                                 A <IBasicProperties> .Ignored,
                                                 A <ReadOnlyMemory <byte> > .Ignored))
            .MustNotHaveHappened();

            Assert.IsFalse(consumeAbortedCalled);
        }
示例#2
0
        public async Task ShouldProperlyStopConsumingMessages(int numberOfMessages)
        {
            var channelMock    = new Mock <IModel>();
            var connectionMock = new Mock <IConnection>();

            connectionMock.Setup(x => x.CreateModel())
            .Returns(channelMock.Object);

            var connectionFactoryMock = new Mock <IRabbitMqConnectionFactory>();

            connectionFactoryMock.Setup(x => x.CreateRabbitMqConnection(It.IsAny <RabbitMqClientOptions>()))
            .Returns(connectionMock.Object);

            var consumer = new AsyncEventingBasicConsumer(channelMock.Object);

            connectionFactoryMock.Setup(x => x.CreateConsumer(It.IsAny <IModel>()))
            .Returns(consumer);

            var messageHandlingPipelineExecutingServiceMock = new Mock <IMessageHandlingPipelineExecutingService>();
            var queueService = CreateService(connectionFactoryMock.Object, messageHandlingPipelineExecutingServiceMock.Object);

            queueService.StartConsuming();
            for (var i = 1; i <= numberOfMessages; i++)
            {
                await consumer.HandleBasicDeliver(
                    "1",
                    (ulong)numberOfMessages,
                    false,
                    "exchange",
                    "routing,key",
                    null,
                    new ReadOnlyMemory <byte>());
            }

            messageHandlingPipelineExecutingServiceMock.Verify(x => x.Execute(It.IsAny <BasicDeliverEventArgs>(), It.IsAny <IQueueService>()), Times.Exactly(numberOfMessages));

            queueService.StopConsuming();
            await consumer.HandleBasicDeliver(
                "1",
                0,
                false,
                "exchange",
                "routing,key",
                null,
                new ReadOnlyMemory <byte>());

            messageHandlingPipelineExecutingServiceMock.Verify(x => x.Execute(It.IsAny <BasicDeliverEventArgs>(), It.IsAny <IQueueService>()), Times.Exactly(numberOfMessages));
        }
示例#3
0
        public void StartReceivingMessages_InvokesCallbackWithCorrectEventMessage()
        {
            // Arrange
            var channelMock = new Mock <IModel>();
            AsyncEventingBasicConsumer basicConsumer = null;

            channelMock.Setup(c => c.BasicConsume("TestQueue",
                                                  true,
                                                  "",
                                                  false,
                                                  false,
                                                  null,
                                                  It.IsAny <AsyncEventingBasicConsumer>()))
            .Callback((string queue,
                       bool autoAck,
                       string consumerTag,
                       bool noLocal,
                       bool exclusive,
                       IDictionary <string, object> arguments,
                       IBasicConsumer consumer) =>
            {
                basicConsumer = consumer as AsyncEventingBasicConsumer;
            });

            var connectionMock = new Mock <IConnection>();

            connectionMock.Setup(c => c.CreateModel())
            .Returns(channelMock.Object);

            var context  = new RabbitMQBusContext(connectionMock.Object, "TestExchange");
            var receiver = new RabbitMQMessageReceiver(context, "TestQueue", new List <string> {
                "TestTopic2"
            });

            // Act
            bool          callbackWasInvoked = false;
            IEventMessage eventMessage       = null;

            receiver.StartReceivingMessages((e) =>
            {
                callbackWasInvoked = true;
                eventMessage       = e;
            });
            var properties = new BasicProperties
            {
                Type          = "Test type",
                Timestamp     = new AmqpTimestamp(1542183431),
                CorrelationId = "test id"
            };

            basicConsumer.HandleBasicDeliver("", 0, false, "", "routing.key", properties, Encoding.UTF8.GetBytes("test message")).Wait();

            // Assert
            Assert.IsTrue(callbackWasInvoked);
            Assert.AreEqual("routing.key", eventMessage.RoutingKey);
            Assert.AreEqual("test message", eventMessage.Message);
            Assert.AreEqual("Test type", eventMessage.EventType);
            Assert.AreEqual(1542183431, eventMessage.Timestamp);
            Assert.AreEqual("test id", eventMessage.CorrelationId);
        }
示例#4
0
        public async Task ConsumerTriggersMessageReceiver()
        {
            var channelMock      = new Mock <IModel>();
            var properties       = new Mock <IBasicProperties>();
            var simulatedPayload = new ReadOnlyMemory <byte>(new byte[] { 1, 1, 1 });
            AsyncEventingBasicConsumer?basicConsumer = null;  // Once the channelMock registers a consumer, we'll fill it in here.

            using var hosted       = new HostedRabbitMqService(_options.Object, _logger.Object, _connectionService.Object, _messageReceiver.Object);
            using var cancellation = new CancellationTokenSource();

            _connectionService.Setup(c => c.GetChannel()).Returns(channelMock.Object);

            // in reality an extension method with a simpler signature is called, but Moq won't allow us to simulate that directly. So we expand the called extension method here.
            channelMock.Setup(c => c.BasicConsume(QueueName, It.IsAny <bool>(), It.IsAny <string>(), It.IsAny <bool>(), It.IsAny <bool>(), It.IsAny <IDictionary <string, object> >(), It.IsAny <AsyncEventingBasicConsumer>()))
            .Callback <string, bool, string, bool, bool, IDictionary <string, object>, IBasicConsumer>((name, autoAck, consumerTag, noLocal, exclusive, arguments, consumer) =>
            {
                // Consumer here is an actual RabbitMQ consumer waiting for our model to fire stuff.
                basicConsumer = consumer as AsyncEventingBasicConsumer;
            });
            _messageReceiver.Setup(m => m.HandleIncoming(typeof(DummyEvent), simulatedPayload)).Returns(Task.CompletedTask).Verifiable("Message receiver was not called!");

            await hosted.StartAsync(cancellation.Token);

            basicConsumer?.HandleBasicDeliver(string.Empty, 420, false, string.Empty, QueueName, properties.Object, simulatedPayload);

            channelMock.Verify();
            _messageReceiver.Verify();
            await hosted.StopAsync(cancellation.Token);
        }
        public async Task ShouldProperlyConsumeMessagesButWithoutAutoAck(int numberOfMessages)
        {
            var channelMock    = new Mock <IModel>();
            var connectionMock = new Mock <IConnection>();
            var consumer       = new AsyncEventingBasicConsumer(channelMock.Object);

            var messageHandlingPipelineExecutingServiceMock = new Mock <IMessageHandlingPipelineExecutingService>();

            const string exchangeName = "exchange";
            var          exchange     = new RabbitMqExchange(exchangeName, ClientExchangeType.Consumption, new RabbitMqExchangeOptions {
                DisableAutoAck = true
            });
            var consumingService = CreateConsumingService(messageHandlingPipelineExecutingServiceMock.Object, new[] { exchange });

            consumingService.UseConnection(connectionMock.Object);
            consumingService.UseChannel(channelMock.Object);
            consumingService.UseConsumer(consumer);

            await consumer.HandleBasicDeliver(
                "1",
                0,
                false,
                exchangeName,
                "routing,key",
                null,
                new ReadOnlyMemory <byte>());

            messageHandlingPipelineExecutingServiceMock.Verify(x => x.Execute(It.IsAny <MessageHandlingContext>()), Times.Never);

            consumingService.StartConsuming();

            for (var i = 1; i <= numberOfMessages; i++)
            {
                await consumer.HandleBasicDeliver(
                    "1",
                    (ulong)numberOfMessages,
                    false,
                    "exchange",
                    "routing,key",
                    null,
                    new ReadOnlyMemory <byte>());
            }

            messageHandlingPipelineExecutingServiceMock.Verify(x => x.Execute(It.IsAny <MessageHandlingContext>()), Times.Exactly(numberOfMessages));
        }
        public async Task ShouldProperlyHandlerMessagesByBatches(ushort prefetchCount, int numberOfMessages)
        {
            const string queueName = "queue.name";

            var channelMock    = new Mock <IModel>();
            var connectionMock = new Mock <IConnection>();

            connectionMock.Setup(x => x.CreateModel())
            .Returns(channelMock.Object);

            var connectionFactoryMock = new Mock <IRabbitMqConnectionFactory>();

            connectionFactoryMock.Setup(x => x.CreateRabbitMqConnection(It.IsAny <RabbitMqServiceOptions>()))
            .Returns(connectionMock.Object);

            var consumer = new AsyncEventingBasicConsumer(channelMock.Object);

            connectionFactoryMock.Setup(x => x.CreateConsumer(It.IsAny <IModel>()))
            .Returns(consumer);

            var callerMock = new Mock <IStubCaller>();

            using var messageHandler = CreateBatchMessageHandler(
                      queueName,
                      prefetchCount,
                      null,
                      connectionFactoryMock.Object,
                      callerMock.Object,
                      Enumerable.Empty <IBatchMessageHandlingMiddleware>());
            await messageHandler.StartAsync(CancellationToken.None);

            for (var i = 0; i < numberOfMessages; i++)
            {
                await consumer.HandleBasicDeliver(
                    "1",
                    (ulong)i,
                    false,
                    "exchange",
                    "routing,key",
                    null,
                    new ReadOnlyMemory <byte>());
            }

            var numberOfBatches = numberOfMessages / prefetchCount;

            callerMock.Verify(x => x.EmptyCall(), Times.Exactly(numberOfBatches));

            var processedMessages = numberOfBatches * prefetchCount;

            callerMock.Verify(x => x.Call(It.IsAny <ReadOnlyMemory <byte> >()), Times.Exactly(processedMessages));

            await messageHandler.StopAsync(CancellationToken.None);
        }
示例#7
0
        public async Task ShouldProperlyConsumeMessages(int numberOfMessages)
        {
            var channelMock    = new Mock <IModel>();
            var connectionMock = new Mock <IConnection>();
            var consumer       = new AsyncEventingBasicConsumer(channelMock.Object);

            var messageHandlingPipelineExecutingServiceMock = new Mock <IMessageHandlingPipelineExecutingService>();
            var consumingService = CreateConsumingService(messageHandlingPipelineExecutingServiceMock.Object);

            consumingService.UseConnection(connectionMock.Object);
            consumingService.UseChannel(channelMock.Object);
            consumingService.UseConsumer(consumer);

            await consumer.HandleBasicDeliver(
                "1",
                0,
                false,
                "exchange",
                "routing,key",
                null,
                new ReadOnlyMemory <byte>());

            messageHandlingPipelineExecutingServiceMock.Verify(x => x.Execute(It.IsAny <BasicDeliverEventArgs>(), It.IsAny <IConsumingService>()), Times.Never);

            consumingService.StartConsuming();

            for (var i = 1; i <= numberOfMessages; i++)
            {
                await consumer.HandleBasicDeliver(
                    "1",
                    (ulong)numberOfMessages,
                    false,
                    "exchange",
                    "routing,key",
                    null,
                    new ReadOnlyMemory <byte>());
            }

            messageHandlingPipelineExecutingServiceMock.Verify(x => x.Execute(It.IsAny <BasicDeliverEventArgs>(), It.IsAny <IConsumingService>()), Times.Exactly(numberOfMessages));
        }
        public async Task ShouldProperlyHandlerMessagesByTimer(int numberOfMessages)
        {
            const string queueName      = "queue.name";
            const ushort prefetchCount  = 10;
            var          handlingPeriod = TimeSpan.FromMilliseconds(100);

            var channelMock    = new Mock <IModel>();
            var connectionMock = new Mock <IConnection>();

            connectionMock.Setup(x => x.CreateModel())
            .Returns(channelMock.Object);

            var connectionFactoryMock = new Mock <IRabbitMqConnectionFactory>();

            connectionFactoryMock.Setup(x => x.CreateRabbitMqConnection(It.IsAny <RabbitMqServiceOptions>()))
            .Returns(connectionMock.Object);

            var consumer = new AsyncEventingBasicConsumer(channelMock.Object);

            connectionFactoryMock.Setup(x => x.CreateConsumer(It.IsAny <IModel>()))
            .Returns(consumer);

            using var waitHandle = new AutoResetEvent(false);
            var callerMock = new Mock <IStubCaller>();
            var caller     = new StubCallerDecorator(callerMock.Object)
            {
                WaitHandle = waitHandle
            };

            using var messageHandler = CreateBatchMessageHandler(
                      queueName,
                      prefetchCount,
                      handlingPeriod,
                      connectionFactoryMock.Object,
                      caller,
                      Enumerable.Empty <IBatchMessageHandlingMiddleware>());
            await messageHandler.StartAsync(CancellationToken.None);

            const int smallBatchSize       = prefetchCount - 1;
            var       numberOfSmallBatches = (int)Math.Ceiling((double)numberOfMessages / smallBatchSize);

            for (var b = 0; b < numberOfSmallBatches; b++)
            {
                var lowerBound = b * smallBatchSize;
                var upperBound = (b + 1) * smallBatchSize > numberOfMessages ? numberOfMessages : (b + 1) * smallBatchSize;
                for (var i = lowerBound; i < upperBound; i++)
                {
                    await consumer.HandleBasicDeliver(
                        "1",
                        (ulong)i,
                        false,
                        "exchange",
                        "routing,key",
                        null,
                        new ReadOnlyMemory <byte>());
                }

                waitHandle.WaitOne(_globalTestsTimeout);
            }

            callerMock.Verify(x => x.EmptyCall(), Times.Exactly(numberOfSmallBatches));
            callerMock.Verify(x => x.Call(It.IsAny <ReadOnlyMemory <byte> >()), Times.Exactly(numberOfMessages));

            await messageHandler.StopAsync(CancellationToken.None);
        }
        public async Task ShouldProperlyExecutePipeline()
        {
            const ushort prefetchCount = 5;
            const string queueName     = "queue.name";

            var channelMock    = new Mock <IModel>();
            var connectionMock = new Mock <IConnection>();

            connectionMock.Setup(x => x.CreateModel())
            .Returns(channelMock.Object);

            var connectionFactoryMock = new Mock <IRabbitMqConnectionFactory>();

            connectionFactoryMock.Setup(x => x.CreateRabbitMqConnection(It.IsAny <RabbitMqServiceOptions>()))
            .Returns(connectionMock.Object);

            var consumer = new AsyncEventingBasicConsumer(channelMock.Object);

            connectionFactoryMock.Setup(x => x.CreateConsumer(It.IsAny <IModel>()))
            .Returns(consumer);

            var callerMock = new Mock <IStubCaller>();

            var orderingMap      = new Dictionary <int, int>();
            var firstMiddleware  = new StubBatchMessageHandlingMiddleware(1, orderingMap);
            var secondMiddleware = new StubBatchMessageHandlingMiddleware(2, orderingMap);
            var thirdMiddleware  = new StubBatchMessageHandlingMiddleware(3, orderingMap);

            var middlewares = new List <IBatchMessageHandlingMiddleware>
            {
                firstMiddleware,
                secondMiddleware,
                thirdMiddleware
            };

            using var messageHandler = CreateBatchMessageHandler(
                      queueName,
                      prefetchCount,
                      null,
                      connectionFactoryMock.Object,
                      callerMock.Object,
                      middlewares);
            await messageHandler.StartAsync(CancellationToken.None);

            for (var i = 0; i < prefetchCount; i++)
            {
                await consumer.HandleBasicDeliver(
                    "1",
                    (ulong)i,
                    false,
                    "exchange",
                    "routing,key",
                    null,
                    new ReadOnlyMemory <byte>());
            }

            callerMock.Verify(x => x.EmptyCall(), Times.Once);
            Assert.Equal(1, orderingMap[thirdMiddleware.Number]);
            Assert.Equal(2, orderingMap[secondMiddleware.Number]);
            Assert.Equal(3, orderingMap[firstMiddleware.Number]);

            await messageHandler.StopAsync(CancellationToken.None);
        }