Fluent Validation

Component: FluentValidation Message Validator
NuGet Package NServiceBus.FluentValidation (3.x)
This is a community maintained project
Target NServiceBus Version: 7.x

Uses the NServiceBus.FluentValidation component to validate various properties of the incoming message and outgoing messages.

Code walk-through

Adding the fluent message validator

In the snippet below, a fluent AbstractValidator for the type MyMessage is created with a rule to check that the Content property of the message is not empty.

public class MyMessageValidator :
    AbstractValidator<MyMessage>
{
    public MyMessageValidator()
    {
        RuleFor(_ => _.Content)
            .NotEmpty();
    }
}

Configuring the endpoint

The validator is then registered in the endpoint configuration as shown in the snippet below. The validation used in this sample is for incoming messages only, so the validator configuration is disabled for outgoing messages. Validators are scanned on start up and registered and resolved using the container.

var validation = configuration.UseFluentValidation(outgoing: false);
validation.AddValidatorsFromAssemblyContaining<MyMessage>();

Running the project

  1. Start the solution.
  2. Two messages of type, MyMessage are automatically sent to the endpoint on start up. The first message has a value for the Content property and the second message has an empty value.
  3. The handler for the message whose Content property has been set will be handled correctly while a validation exception will be thrown for the message whose Content property is empty.

Testing

Message validation can be performed during tests. This is done using a combination of the NServiceBus Testing functionality and the NServiceBus.FluentValidation.Testing NuGet package.

Handler with a bug

OtherMessage requires the Content property to be set. However the below handler has a bug in that that property is not set:

public class OtherHandler :
    IHandleMessages<MyMessage>
{
    public Task Handle(MyMessage message, IMessageHandlerContext context)
    {
        return context.SendLocal(new OtherMessage());
    }
}

Testing with NServiceBus Testing

When using NServiceBus Testing a handlers behavior would be tested as follows:

[Fact]
public async Task IncorrectlyPasses()
{
    var message = new MyMessage();
    var context = new TestableMessageHandlerContext();
    var handler = new OtherHandler();
    await handler.Handle(message, context);
    Assert.IsType<OtherMessage>(context.SentMessages.Single().Message);
}

This test will incorrectly pass, since the handler sends an invalid message.

Messages validated during tests

During test execution outgoing messages can be validated.

[Fact]
public async Task ThrowsForOutgoing()
{
    var message = new MyMessage
    {
        Content = "TheContent"
    };
    var context = ValidatingContext.Build(message);
    var handler = new OtherHandler();
    await context.Run(handler);
    Assert.IsType<OtherMessage>(context.SentMessages.Single().Message);
}

Incoming messages can also be validated. This would usually be indicative of a bug in the test, i.e. the test in not passing in a valid message.

[Fact]
public async Task ThrowsForIncoming()
{
    var message = new MyMessage();
    var context = ValidatingContext.Build(message);
    var handler = new OtherHandler();
    await context.Run(handler);
    Assert.IsType<OtherMessage>(context.SentMessages.Single().Message);
}

Add validators

To enable this functionality validators should be loaded into TestContextValidator before any tests run.

TestContextValidator.AddValidatorsFromAssemblyContaining<MyMessage>();

Last modified