Search code examples
c#.net-coremockingfluentvalidation

How to mock FluentValidation ValidationResults in test


This is the method that I want to test:

public async Task<object> CreateExpense(CreateExpenseCommand command)
{
    var validationResults = await _validator.ValidateAsync(command);
    if (!validationResults.IsValid)
    {
        return validationResults.Errors.First().ToString();
    }
    //more code that is irrelevant for this post
}

To test this, I need to mock _validatior, which is defined as private readonly IValidator<CreateExpenseCommand> _validator; and is used through constructor injection.

I am using AutoFixture with AutoMoqCustomizations and Moq for mocking. Maybe I should use Moq exclusively?

This is what I try to do in the test:

[Fact]
public async Task CreateExpense_Success()
{
    //Arrange
    var service = _fixture.Fixture.Freeze<Mock<IValidator<CreateExpenseCommand>>>();
    service.Setup(x => x.Validate((CreateExpenseCommand)It.IsAny<IValidator<CreateExpenseCommand>>())).Returns(It.IsAny<ValidationResult>);
    
    //more code that is irrelevant for this post
}

However, this results in error:

System.NullReferenceException: 'Object reference not set to instance of an object'.

The error is pretty self-explanatory, but I don't know how to mock correctly.

Image of error:enter image description here


Solution

  • I am very late to answer what solved it for me, but here goes:

    namespace ExpenseTests.Application
    {
        public class CreateExpenseServiceTests
        {
            private TestFixture _fixture;
            public CreateExpenseServiceTests()
            {
                _fixture = new TestFixture();
            }
            [Fact]
            public async Task CreateExpense_Success()
            {
                //Arrange
                var expense = _fixture.Fixture.Create<Expense>();
                CreateExpenseCommand command = _fixture.Fixture.Build<CreateExpenseCommand>()
                    .With(c => c.ExpenseCategory, "HOTEL").Create();
                var validationResults = _fixture.Fixture.Create<ValidationResult>();
    
                var addMock = new Mock<ICreateExpense>();
                addMock.Setup(x => x.CreateExpense(command)).ReturnsAsync(expense);
                ICreateExpense addService = addMock.Object;
    
                var validatorMock = new Mock<IValidator<CreateExpenseCommand>>();
                validatorMock.Setup(x => x.Validate(It.IsAny<CreateExpenseCommand>())).Returns(validationResults);
    
                //Act
                var response = await addService.CreateExpense(command);
    
                //Assert
                Assert.Equal(typeof(Expense), response.GetType());
            }
        }
    }
    

    A lot of it is domain code that you can ignore. Let me know if you have further questions - hope it helps a bit.