【问题标题】:Unit test RabbitMQ MessageProducer in an ASP.NET Core Web API在 ASP.NET Core Web API 中对 RabbitMQ MessageProducer 进行单元测试
【发布时间】:2023-02-24 03:51:45
【问题描述】:

我已经按照 RabbitMQ 文档 (https://www.rabbitmq.com/tutorials/tutorial-seven-dotnet.html) 提供的教程设置了一个 MessageProducer,发布者确认了这一点。

我正在使用 XUnit 和 NSubstitute 进行测试,现在我很难对我为 IModel _channel 定义的回调函数的功能进行单元测试。

如果我只是测试通道是否收到了预期数量的BasicPublish(),测试就会运行完成。

这是我的服务方法:

public async Task SendMessagesWithConfirmAsync<T>(IEnumerable<T> messages, string queueName, string routingKey)
{
    _channel.QueueDeclare(queueName, true, false);

    _channel.ConfirmSelect();

    // Register callbacks to handle acknowledgments
    _channel.BasicAcks += (sender, ea) => CleanOutstandingConfirms(ea.DeliveryTag, ea.Multiple);

    _channel.BasicNacks += (sender, ea) =>
        {
            _outstandingConfirms.TryGetValue(ea.DeliveryTag, out var body);

            Console.WriteLine(
                $"Message with body {body} has been nack-ed. Sequence number: {ea.DeliveryTag}, multiple: {ea.Multiple}");

            CleanOutstandingConfirms(ea.DeliveryTag, ea.Multiple);
    };

    foreach (var message in messages)
    {
        var body = JsonSerializer.Serialize(message);
        _outstandingConfirms.TryAdd(_channel.NextPublishSeqNo, body);
        _channel.BasicPublish(queueName, routingKey, null, Encoding.UTF8.GetBytes(body));
    }

    await Task.CompletedTask;
}

在我的单元测试中,我想确保回调事件被正确触发

[Theory]
[InlineData("Test 1", "Test 2", "Test 3")]
public async void SendMessageWithConfirm_MultipleMessages_ShouldPublishMessagesAndWaitForConfirmOrDie(
    params string[] messages)
{
    // Arrange
    var messageProducer = new RabbitMqMessageProducer(_connectionFactory);

    // Act
    await messageProducer.SendMessagesWithConfirmAsync(messages, "invitations", "invitation");

    // Assert
    _channel.Received(messages.Length).BasicPublish(Arg.Any<string>(), Arg.Any<string>(),
        null, Arg.Any<ReadOnlyMemory<byte>>());

    // Assert on callback events
    // ...
}

另一件事是 _channel.NextPublishSeqNo 永远不会增加。

对此处正确文档的任何帮助或推导将不胜感激。

【问题讨论】:

    标签: c# asp.net-core rabbitmq xunit nsubstitute


    【解决方案1】:

    兔子的单元测试根本不应该检查兔子服务器。 对于 rabbitMQ 服务器,您应该添加集成测试。

    在单元测试中,您检查您的代码,因此您必须添加模拟兔子 MQ 服务器的模拟。

    我使用 Xunit nuget 进行单元测试,使用 moq nuget 模拟 rabbitMQ,如下所示:

    单元测试:

    [Fact]
    public void publish__exchange_declare()
    {
          //Arange
          var rabbitMQMoq = new RabbitMQMoq();
    
          //Act
          var pubRequest = rabbitMQMoq.Publish(new MockEvent());
    
           //Assert
           rabbitMQMoq.DefaultChannel.Verify(m => m.ExchangeDeclare(pubRequest.ExchangeName, pubRequest.ExchangeType.ToString().ToLower(), pubRequest.Durable, false, null));
    }
    

    嘲笑:

      internal class RabbitMQMoq
        {
            #region consts
    
            public const string EXCHANGE_NAME = "TEST";
            public const string DLX_EXCHANGE_NAME = "DLX_TEST";
            public const string QUEUE_NAME = "TEST";
            public const string DLX_QUEUE_NAME = "DLX_TEST";
            public const string ROUTING_KEY = "TEST";
            public const string CONSUMER_TAG = "1234";
            public const ExchangeType EXCHNAGE_TYPE = ExchangeType.Topic;
    
            #endregion
    
            #region properties
            public Mock<IModel> DefaultChannel { get; private set; }
            public Mock<MockEventHandler> EventHandler { get; private set; }
            public Dictionary<string, IAsyncBasicConsumer> Consumers { get; private set; }
            public MojRabbitMQBus Bus { get; private set; }
    
            #endregion
    
            #region c-tor
    
            public RabbitMQMoq(HostConfiguration hostConfiguration= null)
            {
                DefaultChannel = new Mock<IModel>();
                Consumers = new Dictionary<string, IAsyncBasicConsumer>();
                EventHandler = new Mock<MockEventHandler>();
                Bus = CreateRabbitMQBService(hostConfiguration ?? DefaultHostConfiguration);
            }
    
      public PublishExchangeRequest<MockEvent> Publish(MockEvent mockEvent, PublishExchangeRequest<MockEvent> request = null)
            {
                var pubRequest = request ?? CreatePublishExchangeRequest(mockEvent);
    
                Bus.Publish(pubRequest);
    
                return pubRequest;
            }
    
     private Mock<IServiceScopeFactory> CreateServiceScopeFactory()
            {
                var serviceProvider = new Mock<IServiceProvider>();
                serviceProvider
              .Setup(x => x.GetService(typeof(MockEventHandler)))
              .Returns(EventHandler.Object);
                var serviceScope = new Mock<IServiceScope>();
                serviceScope.Setup(x => x.ServiceProvider).Returns(serviceProvider.Object);
                var serviceScopeFactory = new Mock<IServiceScopeFactory>();
                serviceScopeFactory
                    .Setup(x => x.CreateScope())
                    .Returns(serviceScope.Object);
                return serviceScopeFactory;
            }
    }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2015-11-09
      • 2013-11-09
      • 2017-07-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多