-1

Im trying to implement nunit tests with fluentvalidations, but it shows me a failed test and the message: FluentValidation.AsyncValidatorInvokedSynchronouslyException : Validator "AddVehicleCommandValidator" contains asynchronous rules but was invoked synchronously. Please call ValidateAsync rather than Validate.

In my test class I have a test method:

[Test]
public async Task ShouldRequireUniqueId()
{
    var vehicle = await SendAsync(new AddVehicleCommand
    {
        Vehicle = new VehicleDto
        {
            Maker = "BMW",
            Model = "M4",
            UniqueId = "C1"
        }
    });

    await SendAsync(new AddVehicleCommand
    {
        Vehicle = new VehicleDto
        {
            Maker = "BMW",
            Model = "M4",
            UniqueId = "C2"
        }
    });

    var command = new AddVehicleCommand
    {
        Vehicle = new VehicleDto
        {
            Maker = "BMW",
            Model = "M4",
            UniqueId = vehicle.Data.UniqueId
        }
    };

    var exception = FluentActions.Invoking(() => SendAsync(command))
        .Should().ThrowAsync<ValidationException>();
}

Method SendAsync is a generic method for using MediatR and IPipelineBehavior:

public static async Task<TResponse> SendAsync<TResponse>(IRequest<TResponse> request)
{
    using var scope = _scopeFactory.CreateScope();

    var mediator = scope.ServiceProvider.GetService<IMediator>();

    return await mediator.Send(request);
}

also I setup nessery things for registering services at onetimesetup method:

[OneTimeSetUp]
public static void RunBeforeAnyTests()
{
    var builder = WebApplication.CreateBuilder();
    var services = new ServiceCollection();

    var startup = new Startup(_configuration);
    startup.ConfigureServices(services);
    services.AddSingleton(Mock.Of<IWebHostEnvironment>(w => w.ApplicationName == "VehicleReservation.WebApi" && w.EnvironmentName == "Development"));
    _scopeFactory = services.BuildServiceProvider().GetService<IServiceScopeFactory>();
    //_checkpoint = new Checkpoint();
}

So why this test fails? Tnx

UPDATE#1:

[Test]
        public async Task ShouldRequireUniqueId()
        {
            var vehicle = await SendAsync(new AddVehicleCommand
            {
                Vehicle = new VehicleDto
                {
                    Maker = "BMW",
                    Model = "M4",
                    UniqueId = "C1"
                }
            });

            await SendAsync(new AddVehicleCommand
            {
                Vehicle = new VehicleDto
                {
                    Maker = "BMW",
                    Model = "M4",
                    UniqueId = "C2"
                }
            });

            var command = new AddVehicleCommand
            {
                Vehicle = new VehicleDto
                {
                    Maker = "BMW",
                    Model = "M4",
                    UniqueId = vehicle.Data.UniqueId
                }
            };

            var exception = await FluentActions.Awaiting(() => SendAsync(command))
                .Should().ThrowAsync<ValidationException>();
        }
Stefan0309
  • 1,602
  • 5
  • 23
  • 61

1 Answers1

0

The error message you describes an asynchronous validator is synchronously invoked. See https://docs.fluentvalidation.net/en/latest/async.html So somewhere in your code you're blocking the validation.

FluentActions.Invoke takes an Action/Func<T>.

For async execution, use Awaiting

await FluentActions.Awaiting(() => SendAsync(command))
    .Should().ThrowAsync<ValidationException>();
Jonas Nyrup
  • 2,376
  • 18
  • 25
  • please check my update#1. It has still the same error. – Stefan0309 Jan 20 '23 at 08:51
  • What happens if you run `SendAsync(command)` without using Fluent Assertions? If that pass then please add a complete minimal example that I we can post into an IDE and run. – Jonas Nyrup Jan 20 '23 at 11:01