I'm using FluentValidation and MediatR PipelineBehavior to validate the CQRS requests. How should I test this behavior in my unit tests?
Use the test extensions of FluentValidation and I test only the rules.
[Theory] [InlineData(null)] [InlineData("")] [InlineData(" ")] public void Should_have_error_when_name_is_empty(string recipeName) { validator.ShouldHaveValidationErrorFor(recipe => recipe.Name, recipeName); }
Manually validate the request in the unit test
[Theory] [InlineData("")] [InlineData(" ")] public async Task Should_not_create_recipe_when_name_is_empty(string recipeName) { var createRecipeCommand = new CreateRecipeCommand { Name = recipeName, }; var validator = new CreateRecipeCommandValidator(); var validationResult = validator.Validate(createRecipeCommand); validationResult.Errors.Should().BeEmpty(); }
Initialize the PipelineBehavior
[Theory] [InlineData("")] [InlineData(" ")] public async Task Should_not_create_recipe_when_name_is_empty(string recipeName) { var createRecipeCommand = new CreateRecipeCommand { Name = recipeName }; var createRecipeCommandHandler = new CreateRecipeCommand.Handler(_context); var validationBehavior = new ValidationBehavior<CreateRecipeCommand, MediatR.Unit>(new List<CreateRecipeCommandValidator>() { new CreateRecipeCommandValidator() }); await Assert.ThrowsAsync<Application.Common.Exceptions.ValidationException>(() => validationBehavior.Handle(createRecipeCommand, CancellationToken.None, () => { return createRecipeCommandHandler.Handle(createRecipeCommand, CancellationToken.None); }) ); }
Or should I use more of these?
The ValidationBehavior class:
public class ValidationBehavior<TRequest, TResponse> : IPipelineBehavior<TRequest, TResponse>
where TRequest : IRequest<TResponse>
{
private readonly IEnumerable<IValidator<TRequest>> _validators;
public RequestValidationBehavior(IEnumerable<IValidator<TRequest>> validators)
{
_validators = validators;
}
public Task<TResponse> Handle(TRequest request, CancellationToken cancellationToken, RequestHandlerDelegate<TResponse> next)
{
var context = new ValidationContext(request);
var failures = _validators
.Select(v => v.Validate(context))
.SelectMany(result => result.Errors)
.Where(f => f != null)
.ToList();
if (failures.Count != 0)
{
throw new ValidationException(failures);
}
return next();
}
}