如何为IValidatableObject的Validate方法编写xUnit单元测试?
为实现IValidatableObject的Settings类编写xUnit单元测试
首先补全你代码中用到的Category枚举示例(假设定义如下):
public enum Category { TypeA, TypeB }
测试场景与实现
我们需要覆盖两类验证逻辑:数据注解([Required]标注的Id字段)和自定义Validate方法中的枚举合法性校验。以下是完整的xUnit测试类:
using System.Collections.Generic; using System.ComponentModel.DataAnnotations; using Xunit; public class SettingsTests { // 测试Id字段的Required验证 [Fact] public void Settings_WithZeroId_FailsRequiredValidation() { // 准备测试对象 var settings = new Settings { Id = 0, Category = Category.TypeA }; var validationContext = new ValidationContext(settings); var validationResults = new List<ValidationResult>(); // 执行验证 var isValid = Validator.TryValidateObject( settings, validationContext, validationResults, validateAllProperties: true); // 断言结果 Assert.False(isValid); Assert.Contains(validationResults, result => result.MemberNames.Contains(nameof(Settings.Id))); Assert.Contains(validationResults, result => result.ErrorMessage?.Contains("required") ?? false); } // 测试合法枚举值的自定义验证 [Fact] public void Validate_WithValidCategory_ReturnsNoErrors() { // 准备测试对象 var settings = new Settings { Id = 1, Category = Category.TypeB }; var validationContext = new ValidationContext(settings); // 执行自定义验证 var validationResults = settings.Validate(validationContext).ToList(); // 断言结果 Assert.Empty(validationResults); } // 测试非法枚举值的自定义验证 [Fact] public void Validate_WithInvalidCategory_ReturnsError() { // 准备测试对象:使用未定义的枚举值 var settings = new Settings { Id = 1, Category = (Category)999 }; var validationContext = new ValidationContext(settings); // 执行自定义验证 var validationResults = settings.Validate(validationContext).ToList(); // 断言结果 Assert.Single(validationResults); var errorResult = validationResults.First(); Assert.Equal("Invalid Category", errorResult.ErrorMessage); Assert.Contains(nameof(Settings.Category), errorResult.MemberNames); } // 组合验证:同时触发数据注解和自定义验证错误 [Fact] public void Settings_WithInvalidIdAndCategory_ReturnsTwoErrors() { // 准备测试对象 var settings = new Settings { Id = 0, Category = (Category)999 }; var validationContext = new ValidationContext(settings); var validationResults = new List<ValidationResult>(); // 执行全量验证 var isValid = Validator.TryValidateObject( settings, validationContext, validationResults, validateAllProperties: true); // 断言结果 Assert.False(isValid); Assert.Equal(2, validationResults.Count); Assert.Contains(validationResults, r => r.MemberNames.Contains(nameof(Settings.Id))); Assert.Contains(validationResults, r => r.MemberNames.Contains(nameof(Settings.Category))); } }
关于ValidationContext的说明
你的Validate方法中没有使用ValidationContext的任何属性(比如服务提供者、附加项等),因此不需要模拟,直接通过new ValidationContext(settings)实例化即可。如果后续你的验证逻辑需要依赖ValidationContext中的服务(例如从DI容器获取依赖),再考虑使用Moq等框架模拟ValidationContext的相关属性,当前场景完全不需要额外模拟。
内容的提问来源于stack exchange,提问作者sam sergiy klok
相关产品推荐
相关产品推荐

