【问题标题】:ASP.Net MVC: how to write unit test code when working with ValidationAttribute and IClientValidatableASP.Net MVC:使用 ValidationAttribute 和 IClientValidatable 时如何编写单元测试代码
【发布时间】:2016-07-06 03:09:06
【问题描述】:

很抱歉在这里发布类似的问题。我对 asp.net mvc 有点熟悉,但在单元测试中非常新。不要以为我知道很多,只是看看我在 stackoverflow 中的声誉。

我想知道如何为IsValidIEnumerable<ModelClientValidationRule> GetClientValidationRules 编写单元测试代码

我在这里粘贴我的代码,包括我的模型。所以任何人都帮我为上述两个功能编写单元测试代码。我是单元测试新手,使用 VS2013 和使用 VS 单元测试框架。

我的主要问题是如何专门为这个函数编写单元测试代码IEnumerable<ModelClientValidationRule> GetClientValidationRules

所以这是我的完整代码。如果可能,任何经常使用单元测试的人请查看并提供代码和建议。谢谢

型号

public class DateValTest
    {
        [Display(Name = "Start Date")]
        [DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
        public DateTime? StartDate { get; set; }

        [Display(Name = "End Date")]
        [DataType(DataType.Date), DisplayFormat(DataFormatString = "{0:MM/dd/yyyy}", ApplyFormatInEditMode = true)]
        [DateGreaterThanAttribute(otherPropertyName = "StartDate", ErrorMessage = "End date must be greater than start date")]
        public DateTime?  EndDate { get; set; }
    }

自定义验证码

public class DateGreaterThanAttribute : ValidationAttribute, IClientValidatable
    {
        public string otherPropertyName;
        public DateGreaterThanAttribute() { }
        public DateGreaterThanAttribute(string otherPropertyName, string errorMessage)
            : base(errorMessage)
        {
            this.otherPropertyName = otherPropertyName;
        }

        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
        {
            ValidationResult validationResult = ValidationResult.Success;
            try
            {
                // Using reflection we can get a reference to the other date property, in this example the project start date
                var containerType = validationContext.ObjectInstance.GetType();
                var field = containerType.GetProperty(this.otherPropertyName);
                var extensionValue = field.GetValue(validationContext.ObjectInstance, null);
                if(extensionValue==null)
                {
                    //validationResult = new ValidationResult("Start Date is empty");
                    return validationResult;
                }
                var datatype = extensionValue.GetType();

                //var otherPropertyInfo = validationContext.ObjectInstance.GetType().GetProperty(this.otherPropertyName);
                if (field == null)
                    return new ValidationResult(String.Format("Unknown property: {0}.", otherPropertyName));
                // Let's check that otherProperty is of type DateTime as we expect it to be
                if ((field.PropertyType == typeof(DateTime) || (field.PropertyType.IsGenericType && field.PropertyType == typeof(Nullable<DateTime>))))
                {
                    DateTime toValidate = (DateTime)value;
                    DateTime referenceProperty = (DateTime)field.GetValue(validationContext.ObjectInstance, null);
                    // if the end date is lower than the start date, than the validationResult will be set to false and return
                    // a properly formatted error message
                    if (toValidate.CompareTo(referenceProperty) < 1)
                    {
                        validationResult = new ValidationResult(ErrorMessageString);
                    }
                }
                else
                {
                    validationResult = new ValidationResult("An error occurred while validating the property. OtherProperty is not of type DateTime");
                }
            }
            catch (Exception ex)
            {
                // Do stuff, i.e. log the exception
                // Let it go through the upper levels, something bad happened
                throw ex;
            }

            return validationResult;
        }

        public IEnumerable<ModelClientValidationRule> GetClientValidationRules(ModelMetadata metadata, ControllerContext context)
        {
            var rule = new ModelClientValidationRule
            {
                ErrorMessage = FormatErrorMessage(metadata.GetDisplayName()),
                ValidationType = "isgreater",
            };
            rule.ValidationParameters.Add("otherproperty", otherPropertyName);
            yield return rule;
        }
    }

【问题讨论】:

  • var 结果 = 属性.GetClientValidationRules(,.,),ToLIst(); Assert.AreEqual(1, result.Count);

标签: unit-testing visual-studio-2013 asp.net-mvc-5


【解决方案1】:

你要做的是测试如果EndDate的值小于StartDate的值,那么模型是无效的,即IsValid()方法会抛出一个ValidationException

// Test that if the end date is less than the start date its invalid
[TestMethod]
[ExpectedException(typeof(ValidationException))]
public void TestEndDateIsInvalidIfLessThanStartDate()
{
    // Initialize a model with invalid values
    DateValTest model = new DateValTest(){ StartDate = DateTime.Today, EndDate = DateTime.Today.AddDays(-1) };
    ValidationContext context = new ValidationContext(model);
    DateGreaterThanAttribute attribute = new DateGreaterThanAttribute("StartDate");
    attribute.Validate(model.EndDate, context);   
}

当你运行测试时,if 会成功。相反,如果您要使用

初始化模型
DateValTest model = new DateValTest(){ StartDate = DateTime.Today, EndDate = DateTime.Today.AddDays(1) };

测试会失败,因为模型是有效的。

【讨论】:

  • 旁注:IsValid() 方法中的代码存在一些问题,我将在明天更新答案以指出它们。
  • 感谢您的回复和发帖。我也期待这个函数的答案GetClientValidationRules() 但你没有展示如何测试这个函数GetClientValidationRules() 所以我的欧内斯特请求也请展示如何为这个函数编写单元测试代码GetClientValidationRules
  • 您希望测试什么?
  • 我不知道,这就是为什么要求我们不应该为这个函数 GetClientValidationRules() 编写任何单元测试代码,比如 IsValid() ?
  • 为我的这篇文章遮光stackoverflow.com/questions/36116699/…
猜你喜欢
  • 2011-07-25
  • 2015-03-30
  • 2019-03-23
  • 2015-03-12
  • 2013-06-02
  • 2022-10-23
  • 2011-10-11
  • 1970-01-01
相关资源
最近更新 更多