using System.Runtime.CompilerServices;
using MassTransit.Testing;
using Microsoft.Extensions.DependencyInjection;
var shouldThrowOnAssert = true;
var serviceCollection = new ServiceCollection()
.AddMassTransitTestHarness(cfg =>
.AddSagaStateMachine<Machine, MachineState>()
.UsingInMemory((ctx, conf) => conf.ConfigureEndpoints(ctx));
var provider = serviceCollection.BuildServiceProvider(true);
var testHarness = provider.GetTestHarness();
await testHarness.Start();
var sagaHarness = testHarness.GetSagaStateMachineHarness<Machine, MachineState>();
await testHarness.Bus.Publish(new MessageA(id));
AssertTrue(await sagaHarness.Created.Any(x => x.CorrelationId == id));
AssertTrue(await testHarness.Consumed.Any<MessageA>());
AssertTrue(sagaHarness.Created.Count() == 1);
await testHarness.Bus.Publish(new MessageB(id));
AssertTrue(await testHarness.Consumed.Any<MessageB>());
AssertTrue(sagaHarness.Created.Count() == 1);
await testHarness.Bus.Publish(new MessageC(id));
AssertTrue(await testHarness.Consumed.Any<MessageC>());
AssertTrue(sagaHarness.Created.Count() == 1);
await testHarness.OutputTimeline(Console.Out);
[CallerArgumentExpression("t")] string? tExpression = null)
var msg = $"Expected \"{tExpression}\" to be true";
if (shouldThrowOnAssert) throw new Exception(msg);
else Console.WriteLine(msg);
public class MachineState : SagaStateMachineInstance
public State CurrentState { get; set; }
public Guid CorrelationId { get; set; }
public record MessageA(Guid CorrelationId);
public record MessageB(Guid CorrelationId);
public record MessageC(Guid CorrelationId);
public class Machine : MassTransitStateMachine<MachineState>
InstanceState(x => x.CurrentState);
Event(() => OnMessageA, x => x.CorrelateById(m => m.Message.CorrelationId));
Event(() => OnMessageB, x => x.CorrelateById(m => m.Message.CorrelationId));
Event(() => OnMessageC, x => x.CorrelateById(m => m.Message.CorrelationId));
Initially(When(OnMessageA).TransitionTo(A));
During(A, When(OnMessageB).TransitionTo(B));
During(B, When(OnMessageC).TransitionTo(C));
public Event<MessageA> OnMessageA { get; }
public Event<MessageB> OnMessageB { get; }
public Event<MessageC> OnMessageC { get; }