FluentValidation ShouldHaveValidationErrorFor with SetCollectionValidator
Asked Answered
B

3

8

I'm using the FluentValidation library in an ASP.NET MVC project and, from a UI perspective, it's working as expected. Rule violations display the correct errors.

I have a parent class that has a validator and a collection property where that type has a validator. It's conceptually the same as described in the documentation.

I have a validator for a parent class...

public class MyFormValidator : AbstractValidator<MyFormViewModel>

...and I have a collection in MyFormViewModel...

public IList<ChildRow> ChildRowsAdded { get; set; }

...and I create a validator for the collection of that child class...

public class ChildRowValidator : AbstractValidator<ChildRow>

...and I use that child validator in the parent validator...

RuleFor(m => m.ChildRowsAdded).SetCollectionValidator(new ChildRowValidator());

While writing some unit tests, I noticed that ShouldHaveValidationErrorFor is not confirming the errors exist.

_validator.ShouldHaveValidationErrorFor(x => x.ChildRowsAdded, model);

That line in my test does not seem to see the errors. The test fails and the message says

FluentValidation.TestHelper.ValidationTestException : Expected a validation error for property AllergyRowsAdded.

If I manually .Validate() and look at the results, I see the error.

Has anyone run into this before? Is there an additional step I need to take to use ShouldHaveValidationErrorFor in this situation?

Branca answered 5/2, 2015 at 21:57 Comment(2)
I thought that you can use validator.ShouldHaveValidationErrorFor(m => m.Childs[0].Name, model); but it doesn't work either. When I looked into FluentValidation source codes it seems that it is not possible to use ShouldHaveValidationErrorFor assert for this type of test.Drummer
For anyone interested, I cross-posted this on the project's discussion board and got more detail there. fluentvalidation.codeplex.com/discussions/580454#post1351410Branca
B
9

According to the docs, there is another way to test nested properties: a string name that represents the path to the nested property:

// You can also use a string name for properties that can't be easily represented with a lambda, eg:
result.ShouldHaveValidationErrorFor("Addresses[0].Line1");
Bearing answered 20/10, 2021 at 21:2 Comment(0)
M
7

Jookin is absolutely right in his comment:

ShouldHaveValidationErrorFor method doesn't designed to validate properties of properties, you can read about it here.

There are 2 solutions:

  1. Use ShouldHaveValidationErrorFor and test ChildRowValidator directly, like this: _childValidator.ShouldHaveValidationErrorFor(x => x.Name, childModel); // direct descendant property can be validated
  2. Avoid this helper method and use Assert class to check, if in ValidationResult object exists any error with name, that match your array item(s) property by regexp or simple string comparison.

Choose one, that much more meet your purposes.

Mclean answered 10/4, 2015 at 23:10 Comment(0)
P
1

Now, we can do it like that:

in child validator:

RuleForEach(request => request.ChildRowsAdded)
                .SetValidator(new ChildRowValidator())
                .When(request => request.ChildRowsAdded != null); // whatever your rule

And

 var result = _validator.TestValidate(model);
 result.ShouldHaveValidationErrorFor(x => x.ChildRowsAdded);
Piccard answered 13/12, 2022 at 6:35 Comment(0)

© 2022 - 2025 — McMap. All rights reserved.