测试 FluentValidation ChildRules
Testing FluentValidation ChildRules
给定以下对象:
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; }
}
}
我的验证器设置如下:
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");
});
我正在尝试使用这样的测试扩展进行测试:
[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
但是正如您在 'Validation Errors' 下方看到的那样,它实际上已经在验证失败中恢复,但并未将其与此测试联系起来。那么我该如何测试这些 ChildRules 或告诉测试扩展方法 属性 它实际上应该检查哪个?
(我也直接用了validator.ShouldHaveValidationErrorFor
,结果一样)
我以前遇到过这个问题,于是求助于 ShouldHaveValidationErrorFor
使用字符串重载
以下 (nunit) 测试通过
[TestCase(null)]
[TestCase("")]
public void Id_InvalidValue_HasError(string id)
{
var fixture = new Fixture();
var datum = fixture.Build<PatchDTO.Datum>().With(x => x.Id, id).Create();
var dto = fixture.Build<PatchDTO>().With(x => x.Data, new List<PatchDTO.Datum> { datum }).Create();
var validator = new PatchDTOValidator();
var validationResult = validator.TestValidate(dto);
validationResult.ShouldHaveValidationErrorFor("Data[0].Id")
.WithErrorMessage("Invalid 'Data.Id' value");
}
我已经有一段时间没看它了,但我相信问题出在 属性 名称匹配的扩展名 ShouldHaveValidationErrorFor
中,属性 表达式重载没有解决属性 名称更改为 'Data[0].Id'。如果您检查验证结果,您将得到一个看起来像这样的 ValidationError
对象
{
"PropertyName":"Data[0].Id",
"ErrorMessage":"Invalid 'Data.Id' value",
"AttemptedValue":"",
"CustomState":null,
"Severity":0,
"ErrorCode":"NotEmptyValidator",
"FormattedMessageArguments":[
],
"FormattedMessagePlaceholderValues":{
"PropertyName":"Id",
"PropertyValue":""
},
"ResourceName":null
}
编辑:
快速浏览了 属性 表达式重载,如下所示
public IEnumerable<ValidationFailure> ShouldHaveValidationErrorFor<TProperty>(Expression<Func<T, TProperty>> memberAccessor)
{
return ValidationTestExtension.ShouldHaveValidationError(this.Errors, ValidatorOptions.PropertyNameResolver(typeof (T), memberAccessor.GetMember<T, TProperty>(), (LambdaExpression) memberAccessor), true);
}
大概您可以使用 another/write 您自己的 属性 名称解析器来处理这种情况,因为它是可设置的。您可能必须深入研究表达式才能做到这一点。
给定以下对象:
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; }
}
}
我的验证器设置如下:
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");
});
我正在尝试使用这样的测试扩展进行测试:
[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
但是正如您在 'Validation Errors' 下方看到的那样,它实际上已经在验证失败中恢复,但并未将其与此测试联系起来。那么我该如何测试这些 ChildRules 或告诉测试扩展方法 属性 它实际上应该检查哪个?
(我也直接用了validator.ShouldHaveValidationErrorFor
,结果一样)
我以前遇到过这个问题,于是求助于 ShouldHaveValidationErrorFor
以下 (nunit) 测试通过
[TestCase(null)]
[TestCase("")]
public void Id_InvalidValue_HasError(string id)
{
var fixture = new Fixture();
var datum = fixture.Build<PatchDTO.Datum>().With(x => x.Id, id).Create();
var dto = fixture.Build<PatchDTO>().With(x => x.Data, new List<PatchDTO.Datum> { datum }).Create();
var validator = new PatchDTOValidator();
var validationResult = validator.TestValidate(dto);
validationResult.ShouldHaveValidationErrorFor("Data[0].Id")
.WithErrorMessage("Invalid 'Data.Id' value");
}
我已经有一段时间没看它了,但我相信问题出在 属性 名称匹配的扩展名 ShouldHaveValidationErrorFor
中,属性 表达式重载没有解决属性 名称更改为 'Data[0].Id'。如果您检查验证结果,您将得到一个看起来像这样的 ValidationError
对象
{
"PropertyName":"Data[0].Id",
"ErrorMessage":"Invalid 'Data.Id' value",
"AttemptedValue":"",
"CustomState":null,
"Severity":0,
"ErrorCode":"NotEmptyValidator",
"FormattedMessageArguments":[
],
"FormattedMessagePlaceholderValues":{
"PropertyName":"Id",
"PropertyValue":""
},
"ResourceName":null
}
编辑:
快速浏览了 属性 表达式重载,如下所示
public IEnumerable<ValidationFailure> ShouldHaveValidationErrorFor<TProperty>(Expression<Func<T, TProperty>> memberAccessor)
{
return ValidationTestExtension.ShouldHaveValidationError(this.Errors, ValidatorOptions.PropertyNameResolver(typeof (T), memberAccessor.GetMember<T, TProperty>(), (LambdaExpression) memberAccessor), true);
}
大概您可以使用 another/write 您自己的 属性 名称解析器来处理这种情况,因为它是可设置的。您可能必须深入研究表达式才能做到这一点。