public void ConsumeShouldExecuteActionToEachConsumedMessage() { // Arrange var topic = "my-topic"; var consumeResultMock = new ConsumeResult <string, string> { Message = new Message <string, string>() }; var actionMock = new Mock <Action <AgnosticMessage <string> > >(); var producerMock = new Mock <IProducer <string, string> >(); var loggerMock = new Mock <ILogger <KafkaConsumerWrapper <string> > >(); // Simulates a consumer with 3 messages to be read before being terminated. var consumerMock = new Mock <IConsumer <string, string> >(); consumerMock.SetupSequence(consumer => consumer.Consume(It.IsAny <CancellationToken>())) .Returns(consumeResultMock) .Returns(consumeResultMock) .Returns(consumeResultMock) .Throws <OperationCanceledException>(); // Act using (var kafkaConsumerWrapper = new KafkaConsumerWrapper <string>(consumerMock.Object, producerMock.Object, loggerMock.Object)) { kafkaConsumerWrapper.Consume(topic, actionMock.Object); } // Assert actionMock.Verify(action => action(It.IsAny <AgnosticMessage <string> >()), Times.Exactly(3)); }
public void ConsumeShouldStopConsumingAndLeaveGroupWhenCanceled() { // Arrange var topic = "my-topic"; var consumeResultMock = new ConsumeResult <string, string> { Message = new Message <string, string>() }; var actionMock = new Mock <Action <AgnosticMessage <string> > >(); var producerMock = new Mock <IProducer <string, string> >(); var loggerMock = new Mock <ILogger <KafkaConsumerWrapper <string> > >(); // Simulates a consumer being terminated immediately. var consumerMock = new Mock <IConsumer <string, string> >(); consumerMock.SetupSequence(consumer => consumer.Consume(It.IsAny <CancellationToken>())) .Throws <OperationCanceledException>(); // Act using (var kafkaConsumerWrapper = new KafkaConsumerWrapper <string>(consumerMock.Object, producerMock.Object, loggerMock.Object)) { kafkaConsumerWrapper.Consume(topic, actionMock.Object); } // Assert actionMock.Verify(action => action(It.IsAny <AgnosticMessage <string> >()), Times.Never); consumerMock.Verify(consumer => consumer.Close(), Times.Once); }
public void ConsumeShouldSubscribeToTopic() { // Arrange var topic = "my-topic"; var consumeResultMock = new ConsumeResult <string, string> { Message = new Message <string, string>() }; // Simulates a consumer being terminated immediately. var consumerMock = new Mock <IConsumer <string, string> >(); consumerMock.SetupSequence(consumer => consumer.Consume(It.IsAny <CancellationToken>())) .Returns(consumeResultMock) .Throws <OperationCanceledException>(); var producerMock = new Mock <IProducer <string, string> >(); var loggerMock = new Mock <ILogger <KafkaConsumerWrapper <string> > >(); // Act using (var kafkaConsumerWrapper = new KafkaConsumerWrapper <string>(consumerMock.Object, producerMock.Object, loggerMock.Object)) { kafkaConsumerWrapper.Consume(topic, (AgnosticMessage <string> message) => {}); } // Assert consumerMock.Verify(consumer => consumer.Subscribe(topic), Times.Once); }
public async Task OneTopic() { var config = new TestMessageConfiguration(); config.Subscription.Add("TestTopic"); config.IsValid().ShouldBe(true); var stringPropertyValue = "string"; var message = new TestMessage { String = stringPropertyValue }; config.MessagePublishing += async(sender, e) => { e.ShouldBe(config.LatestMessagePublishingEventArgs); e.Topic.ShouldBe("TestTopic"); var strongTyped = JsonConvert.DeserializeObject <TestMessage>(e.Message); strongTyped.String.ShouldBe(stringPropertyValue); }; config.MessageReceiving += async(sender, e) => { e.Topic.ShouldBe("TestTopic"); var strongTyped = JsonConvert.DeserializeObject <TestMessage>(e.Message); strongTyped.String.ShouldBe(stringPropertyValue); }; var publisherWrapper = new KafkaProducerWrapper(config); var receiverWrapper = new KafkaConsumerWrapper(config); var publisher = new MessagePublisher(config, publisherWrapper); receiverWrapper.Connect(); publisherWrapper.Connect(); receiverWrapper.IsConnected.ShouldBe(true); publisherWrapper.IsConnected.ShouldBe(true); await publisher.PublishAsync(message); publisherWrapper.Disconnect(); publisherWrapper.IsConnected.ShouldBe(false); config.LatestMessagePublishingEventArgs.ShouldNotBeNull(); await Task.Delay(10000).ConfigureAwait(false); config.LatestMessageReceivingEventArgs.ShouldNotBeNull(); receiverWrapper.Disconnect(); receiverWrapper.IsConnected.ShouldBe(false); }
public void ConsumeShouldSendMessageToDeadLetterTopicAfterSuccessiveFailedRetries() { // Arrange var topic = "my-topic"; var deadLetterTopic = "_dead-letter_my-topic"; var consumeResultMock = new ConsumeResult <string, string> { Topic = topic, Message = new Message <string, string> { Key = "msg-1" } }; var loggerMock = new Mock <ILogger <KafkaConsumerWrapper <string> > >(); // Simulates an action that always fail. var actionMock = new Mock <Action <AgnosticMessage <string> > >(); actionMock.Setup(action => action(It.Is <AgnosticMessage <string> >(message => message.Key == consumeResultMock.Message.Key))) .Throws <Exception>(); // Simulates a consumer with one message to be read before being terminated. var consumerMock = new Mock <IConsumer <string, string> >(); consumerMock.SetupSequence(consumer => consumer.Consume(It.IsAny <CancellationToken>())) .Returns(consumeResultMock) .Throws <OperationCanceledException>(); var producerMock = new Mock <IProducer <string, string> >(); producerMock.Setup(producer => producer.ProduceAsync(deadLetterTopic, consumeResultMock.Message)) .ReturnsAsync(new DeliveryResult <string, string>()); // Act using (var kafkaConsumerWrapper = new KafkaConsumerWrapper <string>(consumerMock.Object, producerMock.Object, loggerMock.Object)) { kafkaConsumerWrapper.Consume(topic, actionMock.Object); } // Assert actionMock.Verify(action => action(It.IsAny <AgnosticMessage <string> >()), Times.Exactly(4)); producerMock.Verify(producer => producer.ProduceAsync(deadLetterTopic, consumeResultMock.Message), Times.Once); }
public void ConsumeShouldRetryExecutingActionUponFailure() { // Arrange var topic = "my-topic"; var consumeResultMock = new ConsumeResult <string, string> { Message = new Message <string, string> { Key = "msg-1" } }; var producerMock = new Mock <IProducer <string, string> >(); var loggerMock = new Mock <ILogger <KafkaConsumerWrapper <string> > >(); // Simulates an action that fails twice and executes successfully on the third attempt. var actionMock = new Mock <Action <AgnosticMessage <string> > >(); actionMock.SetupSequence(action => action(It.Is <AgnosticMessage <string> >(message => message.Key == consumeResultMock.Message.Key))) .Throws <Exception>() .Throws <Exception>(); // Simulates a consumer with one message to be read before being terminated. var consumerMock = new Mock <IConsumer <string, string> >(); consumerMock.SetupSequence(consumer => consumer.Consume(It.IsAny <CancellationToken>())) .Returns(consumeResultMock) .Throws <OperationCanceledException>(); // Act using (var kafkaConsumerWrapper = new KafkaConsumerWrapper <string>(consumerMock.Object, producerMock.Object, loggerMock.Object)) { kafkaConsumerWrapper.Consume(topic, actionMock.Object); } // Assert actionMock.Verify(action => action(It.IsAny <AgnosticMessage <string> >()), Times.Exactly(3)); }
public async Task SpecifingTopics() { var config = new TestMessageConfiguration(); var pubCount = 0; var subCount = 0; var subTopicList = new List <string>(); config.IsValid().ShouldBe(true); var stringPropertyValue = "string"; var message1 = new TestMessage { String = stringPropertyValue }; var message2 = new TestMessage2 { String = stringPropertyValue }; var message3 = new TestMessage3 { String = stringPropertyValue }; config.MessagePublishing += async(sender, e) => { pubCount++; e.ShouldBe(config.LatestMessagePublishingEventArgs); new[] { "TestTopic", "2TestTopic", "3TestTopic" } .ShouldContain(e.Topic); var strongTyped = JsonConvert.DeserializeObject <TestMessage>(e.Message); strongTyped.String.ShouldBe(stringPropertyValue); }; config.Subscription.Add("2TestTopic"); config.Subscription.Add("3TestTopic"); config.MessageReceiving += async(sender, e) => { subCount++; subTopicList.Add(e.Topic); config.Subscription.ShouldContain(e.Topic); var strongTyped = JsonConvert.DeserializeObject <TestMessage>(e.Message); strongTyped.String.ShouldBe(stringPropertyValue); }; var publisherWrapper = new KafkaProducerWrapper(config); var receiverWrapper = new KafkaConsumerWrapper(config); var publisher = new MessagePublisher(config, publisherWrapper); receiverWrapper.Connect(); publisherWrapper.Connect(); await publisher.PublishAsync(message1); await publisher.PublishAsync(message2); await publisher.PublishAsync(message3); publisherWrapper.Disconnect(); await Task.Delay(10000).ConfigureAwait(false); receiverWrapper.Disconnect(); config.LatestMessagePublishingEventArgs.ShouldNotBeNull(); config.LatestMessageReceivingEventArgs.ShouldNotBeNull(); pubCount.ShouldBe(3); subCount.ShouldBe(2); }