首页 > 解决方案 > MassTransit - Unit Testing a Large Payload Consumer

问题描述

Using the InMemoryTestHarness, I am working on unit testing a Consumer that handles a command with a MessageData property. Using the InMemoryMessageDataRepository to populate the MessageData property works fine however, when the consumer attempts to load the payload (message.Body.Value) I am receiving the following exception: "The message data was not loaded: urn:msgdata:xxxxxxxxxxxxxxxxxxxxxxxxxx"}. What is the proper way to unit test a consumer that handles commands with a MessageData property?

I was going to use the In-memory transport, but it doesn't seem like the right approach since the unit test(s) will not receive immediate feedback from the consumer. Ultimately the end goal is for my unit tests to be able assert that specific exceptions are thrown or that the consumer completed successfully without errors.

using System;
using System.Linq;
using System.Threading.Tasks;
using MassTransit;
using MassTransit.MessageData;
using MassTransit.Testing;
using Newtonsoft.Json;
using Xunit;

namespace Test
{
    public class LargePayloadConsumerTest
    {
        [Fact]
        public async Task Consumer_Should_Deserialize_Message()
        {
            var harness = new InMemoryTestHarness();
            var consumer = harness.Consumer<BigMessageConsumer>();
            var command = new BigMessageCommand();
            var dataRepo = new InMemoryMessageDataRepository();

            var largePayload = new BigMessagePayload()
            {
                Id = 1,
                FirstName = "TestFirstName",
                MiddleName = "TestMiddleName",
                LastName = "TestLastName"
            };


            var json = JsonConvert.SerializeObject(largePayload);
            command.Body = await dataRepo.PutString(json);

            var thisWorks = await command.Body.Value;
            await harness.Start();
            await harness.InputQueueSendEndpoint.Send(command);

            Assert.True(harness.Consumed.Select<BigMessageCommand>().Any());
        }

        public class BigMessageConsumer : IConsumer<BigMessageCommand>
        {
            public async Task Consume(ConsumeContext<BigMessageCommand> context)
            {
                try
                {
                    var json = await context.Message.Body.Value;
                    var deserialized = JsonConvert.DeserializeObject<BigMessagePayload>(json);
                    Console.WriteLine($"{deserialized.Id}: {deserialized.FirstName} {deserialized.MiddleName} {deserialized.LastName}");
                }
                catch (Exception e)
                {
                    //throws {"The message data was not loaded: urn:msgdata:xxxxxxxxxxxxxxxxxxxxxxxxxx"}
                    Console.WriteLine(e);
                    throw;
                }
            }
        }

        public class BigMessageCommand
        {
            public MessageData<string> Body { get; set; }
        }

        public class BigMessagePayload
        {
            public int Id { get; set; }
            public string FirstName { get; set; }
            public string LastName { get; set; }
            public string MiddleName { get; set; }
        }
    }
}

标签: c#masstransit

解决方案


您需要配置接收端点来处理消息数据属性,类似于:

e.UseMessageData<BigMessageCommand>(dataRepo);

由于您使用的是测试工具,因此您可以在添加消费者测试工具之前将其添加到接收端点:

void ConfigureReceiveEndpoint(IReceiveEndpointConfigurator configurator)
{
    configurator.UseMessageData<BigMessageCommand>(dataRepo);
}

harness.OnConfigureReceiveEndpoint += ConfigureReceiveEndpoint;

推荐阅读