【问题标题】:How to mock MassTransit Header values in unit test using NSubstitute如何使用 NSubstitute 在单元测试中模拟 MassTransit 标头值
【发布时间】:2021-08-26 04:07:33
【问题描述】:

我正在尝试创建一个单元测试来测试我的 MassTransit (RabbitMq) 消费者。我的消费者需要一个名为UserName 的总线标题键。我已将我的消费者类简化如下。我需要找到一种方法来模拟总线头数据,否则测试在执行时总是会引发异常context.Headers.TryGetHeader("UserName", out object value)

我正在使用 NSubstitute 模拟库。那么如何模拟ConsumeContext<MyDataObject> 类型,并设置模拟头值呢?我更喜欢 NSubstitute

的解决方案
public class MyDataObjectCommand
{
    public string MyProperty { get; set; }
}

// Consumer class
public class MyConsumer : IConsumer<MyDataObjectCommand>
{
    private readonly IHubContext<MessageHub> _hubContext;

    public MyConsumer(IHubContext<MessageHub> hubContext)
    {
        _hubContext = hubContext;
    }

    public async Task Consume(ConsumeContext<MyDataObjectCommand> context)
    {
        var myProperty = context.Message.MyProperty;
        var userName = TryGetHeader(context, "UserName");
        DoSomethingWith(_hubContext, myProperty, userName);
    }

    private string TryGetHeader(ConsumeContext<MyDataObjectCommand> context, string key, bool errorOnNull = true)
    {
        if (context.Headers.TryGetHeader(key, out object value))
        {
            return Convert.ToString(value);
        }

        if (errorOnNull)
        {
            throw new MyConsumerException(_reportName, $"{key} is not found", _hubContext);
        }

        return null;
    }
}


// Unit Test (I'm using XUnit)
public class MyConsumerTests
{
    private readonly IHubContext<MessageHub> _hubContext;

    public MyConsumerTests()
    {
       _hubContext = Substitute.For<IHubContext<MessageHub>>();
    }

    [Fact]
    public async Task ShouldConsume()
    {
        // arrange
        var mockDataObject = new MyDataObjectCommand() { MyProperty = "x" };

        var harness = new InMemoryTestHarness();
        harness.Consumer(() => new MyConsumer(_hubContext));

        // I need to mock header values on ConsumeContext<MyDataObjectCommand> object here
        // but how do I do it using NSubstitute?
        // context.Headers["UserName"] = "Bob";  ??

        await harness.Start();
        try
        {
            
            // act
            await harness.InputQueueSendEndpoint.Send(mockDataObject);

            // assert
            Assert.True(await harness.Consumed.Any<MyDataObjectCommand>());
            Assert.False(await harness.Consumed.Any<Fault<MyDataObjectCommand>>());
            //Assert.Equal(context.Header["UserName"], "Bob"); How do I do the assertion??
        }
        finally
        {
            await harness.Stop();
        }
    }
}

【问题讨论】:

    标签: c# unit-testing rabbitmq masstransit nsubstitute


    【解决方案1】:

    您在使用 MassTransit 时不会模拟标头值,您只需在使用测试工具发送消息时设置它们。对模拟框架的需求绝对

    await harness.InputQueueSendEndpoint.Send(mockDataObject, 
        context => context.Headers.Set(“UserName”, “Bob”));
    

    当消息传递给消费者时,标头将在ConsumeContext 上可用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-03-24
      • 1970-01-01
      • 1970-01-01
      • 2019-10-09
      • 2017-06-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多