Skip to content

Latest commit

 

History

History
275 lines (237 loc) · 7.47 KB

readme.md

File metadata and controls

275 lines (237 loc) · 7.47 KB

Verify.MassTransit

Discussions Build status NuGet Status

Adds Verify support for MassTransit test helpers.

See Milestones for release notes.

NuGet package

https://nuget.org/packages/Verify.MassTransit/

Usage

[ModuleInitializer]
public static void Initialize() =>
    VerifyMassTransit.Initialize();

snippet source | anchor

Consumer Test

Using traditional asserts consumer interactions can be tested as follows:

[Fact]
public async Task TestWithAsserts()
{
    using var harness = new InMemoryTestHarness();
    var consumerHarness = harness.Consumer<SubmitOrderConsumer>();

    await harness.Start();
    try
    {
        await harness.InputQueueSendEndpoint
            .Send(
                new SubmitOrder
                {
                    OrderId = InVar.Id
                });

        // did the endpoint consume the message
        Assert.True(await harness.Consumed.Any<SubmitOrder>());
        // did the actual consumer consume the message
        Assert.True(await consumerHarness.Consumed.Any<SubmitOrder>());
        // the consumer publish the event
        Assert.True(await harness.Published.Any<OrderSubmitted>());
        // ensure that no faults were published by the consumer
        Assert.False(await harness.Published.Any<Fault<SubmitOrder>>());
    }
    finally
    {
        await harness.Stop();
    }
}

snippet source | anchor

Using Verify, the TestHarness and any number of ConsumerHarness, can be passed to Verify.

[Fact]
public async Task TestWithVerify()
{
    using var harness = new InMemoryTestHarness();
    var consumer = harness.Consumer<SubmitOrderConsumer>();

    await harness.Start();
    try
    {
        await harness.InputQueueSendEndpoint
            .Send(
                new SubmitOrder
                {
                    OrderId = InVar.Id
                });

        await Verify(new
        {
            harness,
            consumer
        });
    }
    finally
    {
        await harness.Stop();
    }
}

snippet source | anchor

The above will result in the following snapshot file that will need to be accepted.

{
  harness: {
    Messages: [
      {
        Sent: ConsumerTests.SubmitOrder,
        MessageId: Guid_1,
        ConversationId: Guid_2,
        DestinationAddress: input_queue,
        Message: {
          OrderId: Guid_3
        }
      },
      {
        Received: ConsumerTests.SubmitOrder,
        MessageId: Guid_1,
        ConversationId: Guid_2,
        DestinationAddress: input_queue,
        Message: {
          OrderId: Guid_3
        }
      },
      {
        Published: ConsumerTests.OrderSubmitted,
        MessageId: Guid_4,
        ConversationId: Guid_2,
        DestinationAddress: Tests:ConsumerTests+OrderSubmitted,
        Message: {
          OrderId: Guid_3
        }
      }
    ]
  },
  consumer: {
    Consumed: [
      {
        Received: ConsumerTests.SubmitOrder,
        MessageId: Guid_1,
        ConversationId: Guid_2,
        DestinationAddress: input_queue,
        Message: {
          OrderId: Guid_3
        }
      }
    ]
  }
}

snippet source | anchor

Moving forward, any change in the message interactions will result in a new snapshot that can then be accepted or declines

Saga Test

The following Saga test:

[Fact]
public async Task Run()
{
    using var harness = new InMemoryTestHarness();
    var sagaHarness = harness.Saga<ConsumerSaga>();

    var correlationId = NewId.NextGuid();

    await harness.Start();
    try
    {
        await harness.Bus.Publish(new Start {CorrelationId = correlationId});

        await harness.Consumed.Any<Start>();

        await Verify(new {harness, sagaHarness});
    }
    finally
    {
        await harness.Stop();
    }
}

public class ConsumerSaga :
    ISaga,
    InitiatedBy<Start>
{
    public Guid CorrelationId { get; set; }
    public bool StartMessageReceived { get; set; }

    public Task Consume(ConsumeContext<Start> context)
    {
        StartMessageReceived = true;
        return Task.CompletedTask;
    }
}

public class Start : CorrelatedBy<Guid>
{
    public Guid CorrelationId { get; init; }
}

snippet source | anchor

Will result in the following snapshot file.

{
  harness: {
    Messages: [
      {
        Published: SagaTests.Start,
        MessageId: Guid_1,
        ConversationId: Guid_2,
        DestinationAddress: Tests:SagaTests+Start,
        Message: {
          CorrelationId: Guid_3
        }
      },
      {
        Received: SagaTests.Start,
        MessageId: Guid_1,
        ConversationId: Guid_2,
        DestinationAddress: Tests:SagaTests+Start,
        Message: {
          CorrelationId: Guid_3
        }
      }
    ]
  },
  sagaHarness: {
    Consumed: [
      {
        Received: SagaTests.Start,
        MessageId: Guid_1,
        ConversationId: Guid_2,
        DestinationAddress: Tests:SagaTests+Start,
        Message: {
          CorrelationId: Guid_3
        }
      }
    ],
    Sagas: [
      {
        Saga: {
          CorrelationId: Guid_3,
          StartMessageReceived: true
        },
        ElementId: Guid_3
      }
    ]
  }
}

snippet source | anchor

Icon

Approval designed by SAM Designs from The Noun Project.