测试FluentValidation ChildRules子规则时匹配异常,如何解决?
问题:FluentValidation测试ChildRules时断言不匹配的解决方法
相关代码实现
1. PatchDTO类定义
public class PatchDTO { public PatchDTO() { Data = new List<Datum>(); } public List<Datum> Data { get; set; } public class Datum { public Datum() { Attributes = new Dictionary<string, object>(); } public string Id { get; set; } public Dictionary<string, object> Attributes { get; set; } } }
2. FluentValidation验证器配置
RuleFor(oo => oo.Data) .NotEmpty() .WithMessage("One or more Data blocks must be provided"); RuleForEach(d => d.Data).ChildRules(datum => { datum.RuleFor(d => d.Id) .NotEmpty() .WithMessage("Invalid 'Data.Id' value"); });
3. 测试用例代码
[Theory] [InlineData(null)] [InlineData("")] public void Id_Failure(string id) { dto.Data[0].Id = id; var result = validator.TestValidate(dto); result.ShouldHaveValidationErrorFor(oo => oo.Data[0].Id) .WithErrorMessage("Invalid 'Data.Id' value"); }
问题现象
运行测试时抛出异常:
FluentValidation.TestHelper.ValidationTestException
HResult=0x80131500
Message=Expected a validation error for property Id
---- Properties with Validation Errors: [0]: Data[0].Id
明明验证器已经检测到Data[0].Id的错误,但测试断言就是匹配不上。
解决方法
这个问题出在FluentValidation的TestHelper对RuleForEach生成的验证规则的属性路径匹配逻辑上,你可以用以下两种方式修复:
方式一:直接使用属性路径字符串断言
把lambda表达式替换成完整的属性路径字符串,让TestHelper能精准匹配到错误位置:
result.ShouldHaveValidationErrorFor("Data[0].Id") .WithErrorMessage("Invalid 'Data.Id' value");
方式二:针对集合元素的属性进行断言
利用RuleForEach的特性,通过指向集合中元素的属性来匹配验证错误:
result.ShouldHaveValidationErrorFor(x => x.Data.Select(d => d.Id)) .WithErrorMessage("Invalid 'Data.Id' value");
另外也可以结合错误码来提升断言的精准度,避免和其他规则的错误信息混淆:
result.ShouldHaveValidationErrorFor(x => x.Data[0].Id) .WithErrorCode("NotEmpty") .WithErrorMessage("Invalid 'Data.Id' value");
最后别忘了确保测试前dto实例已经正确初始化——比如提前创建PatchDTO并往Data集合里添加至少一个Datum对象,避免空引用影响测试结果。
内容的提问来源于stack exchange,提问作者Jim N
相关产品推荐
相关产品推荐

