Excalibur.Dispatch.Testing.Shouldly 3.0.0-alpha.42

This is a prerelease version of Excalibur.Dispatch.Testing.Shouldly.
There is a newer prerelease version of this package available.
See the version list below for details.
dotnet add package Excalibur.Dispatch.Testing.Shouldly --version 3.0.0-alpha.42
                    
NuGet\Install-Package Excalibur.Dispatch.Testing.Shouldly -Version 3.0.0-alpha.42
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Excalibur.Dispatch.Testing.Shouldly" Version="3.0.0-alpha.42" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Excalibur.Dispatch.Testing.Shouldly" Version="3.0.0-alpha.42" />
                    
Directory.Packages.props
<PackageReference Include="Excalibur.Dispatch.Testing.Shouldly" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Excalibur.Dispatch.Testing.Shouldly --version 3.0.0-alpha.42
                    
#r "nuget: Excalibur.Dispatch.Testing.Shouldly, 3.0.0-alpha.42"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Excalibur.Dispatch.Testing.Shouldly@3.0.0-alpha.42
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Excalibur.Dispatch.Testing.Shouldly&version=3.0.0-alpha.42&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Excalibur.Dispatch.Testing.Shouldly&version=3.0.0-alpha.42&prerelease
                    
Install as a Cake Tool

Excalibur.Dispatch.Testing.Shouldly

Shouldly assertion extensions for Excalibur testing. Provides fluent, readable assertions for message dispatch verification.

Installation

dotnet add package Excalibur.Dispatch.Testing.Shouldly

Requires:

  • Excalibur.Dispatch.Testing (core test infrastructure)
  • Shouldly (assertion library)

Features

  • 9 extension methods for IDispatchedMessageLog, InMemoryTransportSender, InMemoryTransportReceiver
  • Fluent assertions aligned with Shouldly conventions
  • Clear failure messages that describe what was expected vs. what actually happened
  • Same namespace as core Testing package - no extra using needed

Quick Start

using Excalibur.Dispatch.Testing; // Extensions auto-discovered

// Arrange
var harness = new DispatchTestHarness();
harness.ConfigureDispatch(d => d.AddHandlersFromAssembly(typeof(MyHandler).Assembly));

// Act
await harness.Dispatcher.DispatchAsync(new OrderCreated { Id = 123 });

// Assert - fluent Shouldly extensions
harness.Dispatched.ShouldHaveDispatched<OrderCreated>();
harness.Dispatched.ShouldNotHaveDispatched<OrderCancelled>();

IDispatchedMessageLog Extensions

Assert on messages captured during pipeline execution.

// Verify message was dispatched
harness.Dispatched.ShouldHaveDispatched<OrderCreated>();

// Verify message was NOT dispatched
harness.Dispatched.ShouldNotHaveDispatched<OrderCancelled>();

// Verify exact count of a message type
harness.Dispatched.ShouldHaveDispatched<OrderCreated>(expectedCount: 2);

// Verify total dispatched count
harness.Dispatched.ShouldHaveDispatchedCount(3);

InMemoryTransportSender Extensions

Assert on transport send operations.

var sender = new InMemoryTransportSender();

// Send messages
await sender.SendAsync(new TransportMessage(...), CancellationToken.None);
await sender.SendAsync(new TransportMessage(...), CancellationToken.None);
await sender.SendAsync(new TransportMessage(...), CancellationToken.None);

// Verify send count
sender.ShouldHaveSent(3);

// Verify message was sent
sender.ShouldHaveSent(message);

// Verify message NOT sent
sender.ShouldNotHaveSent(message);

InMemoryTransportReceiver Extensions

Assert on transport receive operations.

var receiver = new InMemoryTransportReceiver();

// Queue and process messages
receiver.QueueMessage(new TransportMessage(...));
var message = await receiver.ReceiveAsync(CancellationToken.None);
await receiver.AcknowledgeAsync(message.MessageId, CancellationToken.None);

// Verify acknowledgments
receiver.ShouldHaveAcknowledged(1);
receiver.ShouldHaveAcknowledged(message.MessageId);

// Verify rejections
receiver.ShouldHaveRejected(0);

Complete Example

public class OrderWorkflowTests : IAsyncDisposable
{
    private readonly DispatchTestHarness _harness = new();
    private readonly InMemoryTransportSender _sender = new();

    public OrderWorkflowTests()
    {
        _harness.ConfigureServices(services =>
        {
            services.AddSingleton<ITransportSender>(_sender);
        });

        _harness.ConfigureDispatch(d =>
        {
            d.AddHandlersFromAssembly(typeof(OrderHandler).Assembly);
        });
    }

    [Fact]
    public async Task CreateOrder_ShouldPublishEvent()
    {
        // Arrange
        var command = new CreateOrderCommand { ProductId = 123, Quantity = 2 };

        // Act
        await _harness.Dispatcher.DispatchAsync(command, CancellationToken.None);

        // Assert - fluent Shouldly assertions
        _harness.Dispatched.ShouldHaveDispatched<OrderCreated>(
            evt => evt.ProductId == 123 && evt.Quantity == 2);

        _sender.ShouldHaveSent(1);
        _sender.ShouldHaveSent(msg =>
            msg.Body.Contains("OrderCreated") && msg.Body.Contains("123"));
    }

    [Fact]
    public async Task CancelOrder_ShouldNotPublishCreatedEvent()
    {
        // Arrange
        var command = new CancelOrderCommand { OrderId = 456 };

        // Act
        await _harness.Dispatcher.DispatchAsync(command, CancellationToken.None);

        // Assert
        _harness.Dispatched.ShouldNotHaveDispatched<OrderCreated>();
        _harness.Dispatched.ShouldHaveDispatched<OrderCancelled>();
    }

    public async ValueTask DisposeAsync()
    {
        await _harness.DisposeAsync();
    }
}

Extension Methods Reference

Method Target Description
ShouldHaveDispatched<T>() IDispatchedMessageLog Verify message of type T was dispatched
ShouldHaveDispatched<T>(predicate) IDispatchedMessageLog Verify message matching predicate
ShouldHaveDispatched(message) IDispatchedMessageLog Verify specific message instance
ShouldNotHaveDispatched<T>() IDispatchedMessageLog Verify message of type T was NOT dispatched
ShouldHaveSent(count) InMemoryTransportSender Verify exact send count
ShouldHaveSent(message) InMemoryTransportSender Verify specific message sent
ShouldNotHaveSent(message) InMemoryTransportSender Verify message NOT sent
ShouldHaveAcknowledged(count) InMemoryTransportReceiver Verify acknowledgment count
ShouldHaveRejected(count) InMemoryTransportReceiver Verify rejection count

Failure Messages

Shouldly extensions provide clear failure messages:

// Assertion failure
harness.Dispatched.ShouldHaveDispatched<OrderCreated>();

// Output:
// harness.Dispatched
//     should have dispatched
// Excalibur.Dispatch.Messages.OrderCreated
//     but did not.
// Dispatched messages:
//   [0] Excalibur.Dispatch.Messages.OrderUpdated
//   [1] Excalibur.Dispatch.Messages.OrderCancelled

Documentation

License

MIT

Product Compatible and additional computed target framework versions.
.NET net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 is compatible.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
3.0.0-alpha.44 0 3/16/2026
3.0.0-alpha.43 0 3/16/2026
3.0.0-alpha.42 0 3/16/2026
3.0.0-alpha.41 20 3/16/2026
3.0.0-alpha.33 30 3/15/2026
3.0.0-alpha.31 28 3/15/2026
3.0.0-alpha.26 37 3/5/2026
3.0.0-alpha.19 46 2/26/2026