MassTransit SagaStateMachine testing shouldn't be this hard, should it?

Viewed 477

I'm trying to write unit tests for MassTransit SagaStateMachine.

The SagaStateMachine has some activities associated to it, so I'm having to write a service provider and add it when configuring the receive endpoint.

My issue is when I try to resolve ISagaRepository as InMemorySagaRepository it returns null and hence forth I can't confirm anything actually worked in my mocks.

Is there an easier way to do this? I'm at my wits end.

The activities include a discord socket client which I've mocked and injected in the service provider and you can see my source here: https://github.com/robertkirkham88/NightFuryBot/blob/master/tests/NFB.UI.DiscordBot.Tests/StateMachines/FlightStateMachineTests.cs

Line 146 is where the issue lies but I might be doing something wrong with my setting up the bus. The unit tests on MassTransit and Automatonymous are not helpful and I can't find any other solution on git/stackoverflow.

var repo = this.provider.GetService<ISagaRepository<FlightState>>() as InMemorySagaRepository<FlightState>;
Assert.NotNull(repo);
2 Answers

I had the similar problem. I want to test state machine sage with activities resolved via DI. I've tried solution provided by [@Chris Patterson] (https://stackoverflow.com/a/63999346/14864310) with AddMassTransitInMemoryTestHarness method but it looks like the harness does not consume my messages to the saga. It started to work just after adding the following code before harness start:

harness.OnConfigureInMemoryReceiveEndpoint += cfg =>
{
    cfg.ConfigureSagas(provider.GetRequiredService<IBusRegistrationContext>());
}

await harness.Start();

I'm not sure that it's intended or I've missed something.

Version 7.0.4 of MassTransit included container-based configuration for the InMemoryTestHarness, making it easier to configure tests when using a container.

The Release Notes cover usage, which is also shown below.

Based on the code you linked, you would need:

services.AddMassTransitInMemoryTestHarness(cfg =>
{
    cfg.AddSagaStateMachine<FlightStateMachine, FlightState>()
        .InMemoryRepository();

    cfg.AddSagaTestHarness<FlightState>();
});

And then, once the container is built, you can resolve the test harness and start it.

var harness = provider.GetRequiredService<InMemoryTestHarness>();

await harness.Start();

The state machine should already be configured on an endpoint, so your Publish calls should deliver events to the state machine.

Also, you should only need ISagaRepository<T> to check if sagas are present.

Related