简体   繁体   English

如何使用 NSubstitute 在单元测试中模拟 MassTransit Header 值

[英]How to mock MassTransit Header values in unit test using NSubstitute

I'm trying to create a unit test that will test my MassTransit (RabbitMq) consumer.我正在尝试创建一个单元测试来测试我的 MassTransit (RabbitMq) 消费者。 My consumer is expected a bus header key called UserName .我的消费者需要一个名为UserName的总线 header 键。 I've simplified my consumer class as follows.我已将我的消费者 class 简化如下。 I need to find a way to mock the bus header data otherwise the test will always raise an exception when it executes context.Headers.TryGetHeader("UserName", out object value)我需要找到一种方法来模拟总线 header 数据,否则测试在执行context.Headers.TryGetHeader("UserName", out object value)时总是会引发异常

I'm using the NSubstitute mocking library.我正在使用NSubstitute mocking 库。 So how do I mock the ConsumeContext<MyDataObject> type, and set a mock header value?那么如何模拟ConsumeContext<MyDataObject>类型,并设置模拟 header 值? I prefer a solution with NSubstitute我更喜欢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();
        }
    }
}

You don't mock header values when using MassTransit, you just have to set them when you're sending the message using the test harness.使用 MassTransit 时不要模拟header 值,只需在使用测试工具发送消息时设置它们。 There is absolutely zero need for a mocking framework.对 mocking 框架的需求绝对为零

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

The header will then be available on the ConsumeContext when the message is delivered to the consumer.当消息传递给消费者时,header 将在ConsumeContext上可用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM