如何对自定义验证属性进行单元测试

时间:2011-01-12 08:33:23

标签: c# validation unit-testing asp.net-mvc-2

我有一个自定义的asp.net mvc类验证属性。 我的问题是如何对其进行单元测试? 测试类具有属性是一回事,但这实际上不会测试其中的逻辑。这就是我想要测试的内容。

[Serializable]
[EligabilityStudentDebtsAttribute(ErrorMessage = "You must answer yes or no to all questions")]
public class Eligability
{
    [BooleanRequiredToBeTrue(ErrorMessage = "You must agree to the statements listed")]
    public bool StatementAgree { get; set; }

    [Required(ErrorMessage = "Please choose an option")]
    public bool? Income { get; set; }

.....为简洁而删除     }

[AttributeUsage(AttributeTargets.Class)]
public class EligabilityStudentDebtsAttribute : ValidationAttribute
{
    // If AnyDebts is true then 
    // StudentDebts must be true or false

    public override bool IsValid(object value)
    {
        Eligability elig = (Eligability)value;
        bool ok = true;
        if (elig.AnyDebts == true)
        {
            if (elig.StudentDebts == null)
            {
                ok = false;
            }
        }
        return ok;

    }
}

我尝试按如下方式编写测试,但这不起作用:

[TestMethod]
public void Eligability_model_StudentDebts_is_required_if_AnyDebts_is_true()
{

   // Arrange
   var eligability = new Eligability();
   var controller = new ApplicationController();

   // Act
   controller.ModelState.Clear();
   controller.ValidateModel(eligability);
   var actionResult = controller.Section2(eligability,null,string.Empty);

   // Assert
   Assert.IsInstanceOfType(actionResult, typeof(ViewResult));
   Assert.AreEqual(string.Empty, ((ViewResult)actionResult).ViewName);
   Assert.AreEqual(eligability, ((ViewResult)actionResult).ViewData.Model);
   Assert.IsFalse(((ViewResult)actionResult).ViewData.ModelState.IsValid);
}

ModelStateDictionary不包含此自定义属性的键。 它仅包含标准验证属性的属性。

为什么会这样?

测试这些自定义属性的最佳方法是什么?

3 个答案:

答案 0 :(得分:43)

您的属性EligabilityStudentDebtsAttribute只是一个标准类,就像其他所有内容一样,只需对IsValid()方法进行单元测试。如果它工作正常,请相信Framework,该属性可以正常工作。

所以:

[Test]
public void AttibuteTest()
{
   // arrange
   var value = //.. value to test - new Eligability() ;
   var attrib = new EligabilityStudentDebtsAttribute();

   // act
   var result = attrib.IsValid(value);

   // assert
   Assert.That(result, Is.True)
}

答案 1 :(得分:13)

您的自定义验证属性可能取决于其他属性的状态。在这种情况下,您可以使用System.ComponentModel.DataAnnotations.Validator静态方法,例如:

var model = ...
var context = new ValidationContext(model);
var results = new List<ValidationResult>();
var isValid = Validator.TryValidateObject(model, context, results, true);
Assert.True(isValid);

答案 2 :(得分:0)

我发现IsValid在诸如字符串之类的简单类型上不能很好地工作。例如。如果您对不是对象的字符串查询参数进行了验证。另外,直接在属性上测试值也很容易,而不必提供整个对象。它还允许检查错误消息。它是这样工作的:

string input = "myteststring";
var myAttribute = new MyAttribute()
var result = attribute.GetValidationResult(input, new ValidationContext(input));

var isSuccess = result == ValidationResult.Success;
var errorMessage = result?.ErrorMessage;

此代码仅测试输入值的验证,而没有其他测试。

P.S。我已经在dotnet核心中对此进行了测试,但我认为这也适用于普通dotnet。