Monday, July 10, 2017

Testing FluentValidation PropertyValidator

Leave a Comment

Is it possible to test a FluentValidation PropertyValidator in isolation?

I know I can test the Validator that's using the PropertyValidator for specific errors but I’d rather test true/false just on the property validator if possible.

Can this be done? If so, how?

3 Answers

Answers 1

I also wanted to test my true / false logic. It is a shame the IsValid method is protected. My work around was to create another IsValid method and have the protected IsValid call through to it.

public class MyValidator: PropertyValidator  {     public MyValidator(         string errorMessage = "default Message") : base(errorMessage)     {     }      protected override bool IsValid(PropertyValidatorContext context)     {         var stringToValidate = context.PropertyValue as String;         return IsValid(stringToValidate);     }      public bool IsValid(string stringToValidate)     {         if (stringToValidate == null)         {             return false;         }          //testing logic here         return true;     } } 

Answers 2

I know this has been a while, but I achieved this as follows:

Custom Validator:

public class MyValidator : PropertyValidator {     public MyValidator ()         : base("Value must be null or between 0 and 3.")     {     }      protected override bool IsValid(PropertyValidatorContext context)     {         if (context.PropertyValue == null)         {             return true;         }          var value = (decimal)context.PropertyValue;         return value >= 0m && value <= 3m;     } } 

Test Validator:

public class TestValidator : InlineValidator<TestObject> {     public TestValidator (params Action<TestValidator >[] actions)     {         foreach (var action in actions)         {             action(this);         }     } } 

Test Object:

public class TestObject {     public TestObject(decimal? val)     {         this.GenericDecimal = val;     }      public decimal? GenericDecimal { get; set; } } 

Test:

[Test] public void TestIt() {     var validator = new TestValidator(v => v.RuleFor(obj => obj.GenericDecimal).SetValidator( new MyValidator() ));      Assert.IsTrue(validator.Validate(new TestObject(null)).IsValid);         Assert.IsTrue(validator.Validate(new TestObject(0m)).IsValid);        Assert.IsTrue(validator.Validate(new TestObject(3m)).IsValid);        Assert.IsFalse(validator.Validate(new TestObject(-1m)).IsValid);        Assert.IsFalse(validator.Validate(new TestObject(3.01m)).IsValid);    } 

Answers 3

As for version 6.2 of FluentValidation it is possible to build the PropertyValidator.Validate() parameter due to making ValidatorSelectors globally configurable: https://github.com/JeremySkinner/FluentValidation/commit/95376c0519da1a06388be91a97fb5062fd4a162e

In the below example you see how I validate the 'puic' property of Track

Unit test:

    public void ExistsInCollectionValidatorTest()     {         var track = new Track()         {             puic = "p1"         };          var sut = new ExistsInCollectionValidator<Track>();          // Build PropertyValidator.Validate() parameter         var selector = ValidatorOptions.ValidatorSelectors.DefaultValidatorSelectorFactory();         var context = new ValidationContext(track, new PropertyChain(), selector);         var propertyValidatorContext = new PropertyValidatorContext(context, PropertyRule.Create<Track,string>(t => t.puic), "puic");          var results = sut.Validate(propertyValidatorContext);         // Assertion..     } 
If You Enjoyed This, Take 5 Seconds To Share It

0 comments:

Post a Comment