Search code examples
c#integration-testingmasstransit

Integration testing microservices using MassTransit


I am trying to create black box integration tests around some services that I have created using MassTransit. The gist of the service is that it receives a message on a MassTransit channel, processes the message and sends the message on a different MassTransit channel (note that this is not a Request-Reply semantic but more of a component in a pipeline):

IBusControl bus = Bus.Factory.CreateUsingRabbitMq(cfg =>
{
    var host = cfg.Host(new Uri("rabbitmq://localhost"),
        h =>
        {
            h.Username("guest");
            h.Password("guest");
        });

    cfg.ReceiveEndpoint(host, "Queue1", ep =>
    {
        ep.Handler<ItemStarted>(context =>
        {
            ItemFinished item = FinishMessage(context.Message);
            context.Publish(item); 
        });
    });
});

bus.Start();

In order to test this I think what I need is a synchronous way to receive messages from the bus. Is there any way to do this:

IBusControl bus = Bus.Factory.CreateUsingRabbitMq(cfg =>
    var host = cfg.Host(new Uri("rabbitmq://localhost"),
        h =>
        {
            h.Username("guest");
            h.Password("guest");
        }));

bus.Start();

bus.Publish(new ItemStarted());

// This is what does not seem to exist
ItemFinished finished = bus.Receive<ItemFinished>(timeout : Timespan.FromSeconds(5));

// Assertions about finished

Is there a way to receive messages directly from MassTransit without wiring up a consumer class or lambda?


Solution

  • There is a MultiTestConsumer that can be used to receive and track messages that are produced during testing. You can see the class here:

    https://github.com/MassTransit/MassTransit/blob/develop/src/MassTransit/Testing/MultiTestConsumer.cs

    And you can see how it is used here:

    https://github.com/MassTransit/MassTransit/blob/develop/tests/MassTransit.Tests/MultiTestConsumer_Specs.cs

    It can also be used as a regular subscribed consumer, which sets up bindings in RabbitMQ to receive published messages.

    I would recommend checking out the TestFramework, as there are a bunch of asynchronous testing helpers in there.