Search code examples
c#asp.net-mvcunit-testingmoqvalidationattribute

Testing ValidationAttribute that overrides IsValid


I'm having a bit of trouble getting my head around testing my custom validation attribute. As the method signature is protected when I invoke the IsValid method in my unit test, I can't pass in a Mock<ValidationContext> object, it's calling the base virtual bool IsValid(object value) instead.

ValidationAttribute

protected override ValidationResult IsValid(object value, ValidationContext validationContext)
{
    var otherPropertyInfo = validationContext.ObjectType.GetProperty(this.otherPropertyName);
    var otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);

    if (value != null)
    {
        if (otherPropertyValue == null)
        {
            return new ValidationResult(FormatErrorMessage(this.ErrorMessage));
        }
    }

    return ValidationResult.Success;
}

Test

[Test]
public void Should_BeValid_WhenPropertyIsNullAndOtherPropertyIsNull()
{
    var attribute = new OptionalIfAttribute("test");
    var result = attribute.IsValid(null);

    Assert.That(result, Is.True);
}

If I'm unable to pass in a mocked validation context, then how can I test this class properly?


Solution

  • You can use the Validator class to perform the validation manually without having to mock anything. There is a brief article on it here. I would probably do something like

    [Test]
    public void Should_BeValid_WhenPropertyIsNullAndOtherPropertyIsNull()
    {
        var target = new ValidationTarget();
        var context = new ValidationContext(target);
        var results = new List<ValidationResult>();
    
        var isValid = Validator.TryValidateObject(target, context, results, true);
    
        Assert.That(isValid, Is.True);
    }
    
    private class ValidationTarget
    {
        public string X { get; set; }
    
        [OptionalIf(nameof(X))]
        public string OptionalIfX { get; set; }
    }
    

    You could optionally make assertions on results.