Question

I'm sure I'm going about using FluentValidation the wrong way, and I tried searching around but may not be using the right terms. Any help is appreciated.

So, I'm using a library, and because it deals with the file system, I'm mocking it (and thankful it has interfaces so that I can quickly do so!)

The object I'm trying to mock, which represents an excel worksheet, has a method essentially called "IsEmpty(boolean aBooleanToSet)".

I can write this up with Moq along the lines of:

mockWorkbook.Setup(m => m.IsEmpty(It.IsAny<bool>())).Returns(true);

My validator class is pretty simple and looks like the following:

public class InvoiceDetailsWorksheetValidator : AbstractValidator<IXLWorksheet>
{
    public InvoiceDetailsWorksheetValidator()
    {
        RuleFor(x => x.IsEmpty())
            .NotEqual(true).WithMessage("Worksheet must not be empty.");
    }
}

I have the following test, using xUnit.net:

[Fact]
public void Validate_WithFirstWorksheetEmpty_ReturnsInvalid()
{
       // Get the otherwise valid worksheet
       var mockWorkbook = TestHelper.GetMockValidInvoiceDetailsWorksheet();

       // Set the one specific value to a mocked failure
        mockWorkbook.Setup(m => m.IsEmpty(It.IsAny<bool>())).Returns(true);

       // Pass the mock object to the validator
       var validationResults = new InvoiceDetailsWorksheetValidator().Validate(mockWorkbook.Object);

       // Assert that the validator finds it invalid
       Assert.False(validationResults.IsValid);
}

When I run the test, rather than it passing, I see the following error from FluentValidation:

System.InvalidOperationException

Property name could not be automatically determined for expression x => x.IsEmpty().
Please specify either a custom property name by calling 'WithName'.

What am I doing wrong?

Was it helpful?

Solution

Jeremy Skinner, author of FluentValidation, was kind enough to provide me with an explanation on its discussion forum.

Essentially, FluentValidation allows you to test methods, but you have to specify a property name for them because FluentValidation is inherently built to test properties.

So the solution is to take my original validation:

       RuleFor(x=>x.IsEmpty())
            .NotEqual(true).WithMessage("Worksheet must not be empty.");

...and add an OverridePropertyName() method onto the end like so:

       RuleFor(x=>x.IsEmpty())
            .NotEqual(true).WithMessage("Worksheet must not be empty.").OverridePropertyName("IsEmpty");

(As a side note, I very much recommend this library if you need to perform validation on business objects. Very handy, has rarely let me down, and Jeremy is great about supporting the project and its users.)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top