I want to unit test my MassTransit consumer which does not send a response back. Currently my test does seem to be publishing a message, but the consumer is not being triggered, so my breakpoints are not getting hit within it at all.
The consumer is fairly straight forward, but it does have a service injected via DI.
public class BudgetExceededConsumer : IConsumer<IBudgetExceeded>
{
private readonly INotificationHubService _notificationHubService;
public BudgetExceededConsumer(INotificationHubService notificationHubService)
{
_notificationHubService = notificationHubService;
}
public async Task Consume(ConsumeContext<IBudgetExceeded> context)
{
try
{
var message = context.Message;
await _notificationHubService.SendNotificationAsync(context.Message);
}
catch (Exception ex)
{
throw new Exception("Failed to send push notification for exceeding budget usage", ex);
}
}
}
The consumer is added to my Azure function using the following:
builder.Services.AddMassTransitForAzureFunctions(cfg =>
{
cfg.AddConsumersFromNamespaceContaining<ConsumerNamespace>();
});
And I have a relatively straightforward service that is used by other functions to send the messages:
private readonly ISendEndpointProvider _sendEndpoint;
public MessagingService(ISendEndpointProvider sendEndpoint)
{
_sendEndpoint = sendEndpoint;
}
public async Task SendMessage<T>(string queueName, object messageBody) where T : class, MessageBase
{
var endpoint = await _sendEndpoint.GetSendEndpoint(new Uri($"queue:{queueName}"));
await endpoint.Send<T>(messageBody);
}
I would like to write a simple test for the consumer so I could mock the service and then verify that the mocked service is being called. However I cannot get to the point of running a test and my consumer being hit by a breakpoint. I am not setting up the service injected into the consumer anywhere in the DI. Currently it is not complaining about that which makes me think I am missing something in the setup.
public async Task Budget_message_gets_consumed()
{
await using var provider = new ServiceCollection()
.AddMassTransitInMemoryTestHarness(cfg =>
{
cfg.AddConsumer<BudgetExceededConsumer>();
cfg.AddConsumerTestHarness<BudgetExceededConsumer>();
})
.BuildServiceProvider(true);
var harness = provider.GetRequiredService<InMemoryTestHarness>();
await harness.Start();
try
{
var bus = provider.GetRequiredService<IBus>();
BudgetExceededMessage message = new BudgetExceededMessage
{
UserEmailAddress = "test@email.com",
Budget = "£20.00",
TotalSpend = "£23.56"
};
await bus.Publish(message);
var result = await harness.Consumed.Any<IBudgetExceeded>();
Assert.That(result, Is.True); //This is true
var consumerHarness = provider.GetRequiredService<IConsumerTestHarness<BudgetExceededConsumer>>();
var result2 = await consumerHarness.Consumed.Any<IBudgetExceeded>();
Assert.That(result2, Is.True); //This is FALSE.
}
finally
{
await harness.Stop();
await provider.DisposeAsync();
}
}
As you can see the second Assert is false. I think if this was true then I would be seeing the breakpoint in my consumer getting hit.
Is there part of the setup here I need to change so the second assert will get evaluated correctly? I know my setup is slightly different to the docs since I am not using the approach that gives a response.
Thanks