FluentValidation unit tests for classes with sub / child classes

Is it possible to write unit tests for fluentvalidation classes when the object we are testing has child classes that are also being tested.

As an example: My class is as follows

public class TestModel { public class SubData { public int SubDataVal { get; set; } } public int ParentVal { get; set; } public SubData Sub { get; set; } } 

My validation logic is as follows:

 public class TestModelValidator : AbstractValidator<TestModel> { public TestModelValidator() { RuleFor(o => o.ParentVal).GreaterThan(0); RuleFor(o => o.Sub.SubDataVal).GreaterThan(0); } } 

And when I write the next unit test

  [Test] public void Should_have_error_when_val_is_zero() { validator = new TestModelValidator(); validator.ShouldHaveValidationErrorFor(model => model.ParentVal, 0); } 

I get a "Fix System.NullReferenceException: Object not set on the instance of the object." exception from FluentValidation.TestHelper.ValidatorTester`2.ValidateError (T instanceToValidate)

(if I delete the line RuleFor (o => o.Sub.ataVal) .GreaterThan (0); line, then it works!)

Similarly, if I try and unit test the actual child class with:

  [Test] public void Should_have_error_when_sub_dataVal_is_zero() { validator = new TestModelValidator(); validator.ShouldHaveValidationErrorFor(model => model.Sub.SubDataVal, 0); } 

I get "System.Reflection.TargetException: Object does not match the type of the target." from FluentValidation.TestHelper.ValidatorTester`2.ValidateError (T instanceToValidate)

+7
source share
2 answers

Unit test models and child models can, but you will need to modify the validation class to use a separate validation class that simply validates the child model:

 public class TestModelValidator : AbstractValidator<TestModel> { public TestModelValidator() { RuleFor(o => o.ParentVal).GreaterThan(0); RuleFor(o => o.Sub).SetValidator(new SubDataValidator()); } } public class SubDataValidator : AbstractValidator<SubData> { public SubDataValidator() { RuleFor(o => o.SubDataVal).GreaterThan(0); } } 

You can then write your unit tests to test each validator or both together.

+6
source

I came to the conclusion that, for this, ShouldHaveValidationErrorFor is simply impractical to deal with subclasses, therefore, resorting to it manually. i.e.

  [Test] public void Should_have_error_when_val_is_zero() { validator = new TestModelValidator(); TestModel testRequest = new TestModel(); //populate with dummy data var result = validator.Validate(testRequest); Assert.That(result.Errors.Any(o => o.PropertyName== "ParentVal")); } 
+3
source

All Articles