我想使用FluentValidation来验证某些类,其中一个类仅用作另一个类的属性...但我从不直接创建子类,所以我想从父级别测试验证。这可能是不必要的/疯狂的
所以例如我有
public class Parent
{
public string Text {get;set;}
public Child Child {get;set;}
}
public class Child
{
public string Text {get;set;}
}
和
public class ParentValidator : AbstractValidator<Parent>
{
public ParentValidator()
{
RuleFor(p=>p.Text).NotEmpty();
//RuleFor(p=>p.Child).SetValidator(new ChildValidator);
//RuleFor(p=>p.Child.Text).NotEmpty();
}
}
public class ChildValidator : AbstractValidator<Child>
{
public ChildValidator()
{
RuleFor(c=>c.Text).NotEmpty();
}
}
我用
进行测试 [Test]
public void ParentMustHaveText()
{
new ParentValidator()
.ShouldHaveValidationErrorFor(p => p.Text, "");
}
[Test]
public void ChildMustHaveText()
{
new ParentValidator().ShouldHaveValidationErrorFor(p => p.Child.Text, "");
}
无论我如何设置,ChildMustHaveText
测试总是失败。我是否疯狂试图以这种方式进行测试?
因为以下测试总是通过
[Test]
public void ChildMustHaveText()
{
new ChildValidator().ShouldHaveValidationErrorFor(c => c.Text, "");
}
这些类是ASP.NET WebApi项目中的模型。
答案 0 :(得分:6)
第一个错误是您忘记在默认Child
构造函数中指定Parent
属性对象的创建 - FluentValidation尝试设置null
的dynanically属性。
public class Parent
{
public Parent()
{
Child = new Child();
}
public string Text { get; set; }
public Child Child { get; set; }
}
请注意,默认构造函数总是在ShouldHaveValidationErrorFor
中用于在验证之前创建对象。
我发现的下一件事是当前实施 ShouldHaveValidationErrorFor
不允许检查嵌套级别超过1的嵌套属性的有效性 (obj.Child1.Child2.Text
是嵌套的第3级,例如)。
<强> 陷阱 强>
错误地点(FluentValidation.TestHelper.ValidatorTester
类)的源代码:
public void ValidateError(T instanceToValidate) {
accessor.Set(instanceToValidate, value);
//
var count = validator.Validate(instanceToValidate, ruleSet: ruleSet).Errors.Count(x => x.PropertyName == accessor.Member.Name);
if (count == 0) {
throw new ValidationTestException(string.Format("Expected a validation error for property {0}", accessor.Member.Name));
}
}
<强> 说明 强>
方法将连接的属性名称与验证错误(x.PropertyName
)与属性对象System.Reflection.RuntimePropertyInfo
名称(accessor.Member.Name
)进行比较,例如: "Text"
和"Child.Text"
"Text"
用于两项测试,因此测试通过仅因parent.Text
为空,它无效且两个类中的属性名称彼此相等。
如果简化 - 现在您的测试通过了,但错误的原因。
如果重命名字符串属性之一,则可以看到这种奇怪的行为:
public class Child
{
public string Text2 {get;set;}
}
或者如果您在测试中使Parent.Text
属性有效(删除规则,或在Parent()
默认构造函数中初始化非空值)。
public Parent()
{
Child = new Child();
Text = "I like pitfalls";
}
<强> 结论 强>
这是TestHelper课程中的一个错误,我希望这项研究可以帮助您确定应用程序的未来测试策略。
永不放弃! ; - )