C#中如何为Enum配置Data Annotation并使用XUnit做验证测试
解决方案
方案1:使用系统自带RangeAttribute(最简实现)
C#枚举默认基于int类型,枚举值按定义顺序自动分配递增整数值,直接用Range注解即可实现范围校验:
using System.ComponentModel.DataAnnotations; public class MyDTO { [Range(typeof(Month), nameof(Month.March), nameof(Month.October), ErrorMessage = "月份仅允许为3月到10月")] public Month Month{ get; set; } // 对应测试中调用的Validate校验方法 public List<ValidationResult> Validate() { var validationResults = new List<ValidationResult>(); var validationContext = new ValidationContext(this); Validator.TryValidateObject(this, validationContext, validationResults, validateAllProperties: true); return validationResults; } }
注意:该方案依赖枚举底层整数值的递增顺序,若后续调整枚举定义顺序,需要同步更新校验规则。
方案2:自定义校验特性(更稳妥,不受枚举顺序影响)
如果要避免枚举顺序调整导致校验失效,可以自定义专门的枚举范围校验特性:
首先自定义注解类:
using System.ComponentModel.DataAnnotations; public class AllowedMonthAttribute : ValidationAttribute { private static readonly Month[] _allowedMonths = new[] { Month.March, Month.May, Month.June, Month.July, Month.August, Month.September, Month.October }; public override bool IsValid(object? value) { if (value is Month inputMonth) { return _allowedMonths.Contains(inputMonth); } return false; } }
之后在DTO属性上引用该注解即可:
public class MyDTO { [AllowedMonth(ErrorMessage = "月份仅允许为3月到10月")] public Month Month{ get; set; } // 同上的Validate校验方法 public List<ValidationResult> Validate() { var validationResults = new List<ValidationResult>(); var validationContext = new ValidationContext(this); Validator.TryValidateObject(this, validationContext, validationResults, validateAllProperties: true); return validationResults; } }
测试用例修正(符合XUnit规范)
原测试用例存在语法问题,修正后如下:
// 合法值测试用例 [Fact] public void ValidDTO_WithAllowedMonth_ReturnsNoErrors() { var dto = new MyDTO() { Month = Month.March }; var result = dto.Validate(); Assert.Empty(result); } // 非法值测试用例 [Fact] public void InvalidDTO_WithDisallowedMonth_ReturnsError() { var dto = new MyDTO() { Month = Month.February }; var result = dto.Validate(); Assert.Single(result); }
内容的提问来源于stack exchange,提问作者user5113188
相关产品推荐
相关产品推荐

