C# 使用FluentValidator验证属性的子级
我想使用FluentValidation来验证某些类,其中一个类仅用作另一个类的属性。。。但是我从来没有直接创建子类,所以我想从父级测试验证。这可能是不必要的/疯狂的 比如我有C# 使用FluentValidator验证属性的子级,c#,fluentvalidation,C#,Fluentvalidation,我想使用FluentValidation来验证某些类,其中一个类仅用作另一个类的属性。。。但是我从来没有直接创建子类,所以我想从父级测试验证。这可能是不必要的/疯狂的 比如我有 public class Parent { public string Text {get;set;} public Child Child {get;set;} } public class Child { public string Text {get;set;} } 及 无论我如何设置,孩子必须有
public class Parent
{
public string Text {get;set;}
public Child Child {get;set;}
}
public class Child
{
public string Text {get;set;}
}
及
无论我如何设置,孩子必须有文本测试总是失败。我这么做是不是疯了
因为下面的测试总是通过的
[Test]
public void ChildMustHaveText()
{
new ChildValidator().ShouldHaveValidationErrorFor(c => c.Text, "");
}
这些类是ASP.NET WebApi项目中的模型。第一个错误是,您忘记在默认的
父级构造函数-FluentValidation中指定子级属性对象的创建。请尝试设置空值的动态属性
public class Parent
{
public Parent()
{
Child = new Child();
}
public string Text { get; set; }
public Child Child { get; set; }
}
请注意,默认构造函数在验证之前总是使用inshouldlhavevalidationerror来创建对象
我发现的下一件事是,当前的实现不允许检查嵌套级别超过1的嵌套属性的有效性(例如,obj.Child1.Child2.Text
是嵌套级别3)
陷阱
buggy place的源代码(FluentValidation.TestHelper.ValidatorTester
class):
解释
方法将带有验证错误(x.PropertyName
)的联接属性名称与属性对象System.Reflection.RuntimePropertyInfo
名称(accessor.Member.name
)进行比较,例如两个测试的“Text”
和“Child.Text”
都带有“Text”
,所以测试通过仅仅是因为parent.Text
为null,它无效,并且两个类中的属性名称彼此相等
如果简化-现在你的测试通过了,但原因是错误的
如果重命名字符串属性之一,可以看到这种奇怪的行为:
public class Child
{
public string Text2 {get;set;}
}
或者,如果您使Parent.Text
属性在测试中有效(删除规则,或在Parent()
默认构造函数中通过非空值初始化)
结论
这是TestHelper类中的一个bug,我希望这项研究能够帮助您决定应用程序的未来测试策略
永远不要放弃 我不想看起来很傻,但是你的子属性的规则定义都被注释了。是的,这可能不清楚。不管我用什么组合,我都不能通过考试。我最终还是放弃了
public class Parent
{
public Parent()
{
Child = new Child();
}
public string Text { get; set; }
public Child Child { get; set; }
}
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));
}
}
public class Child
{
public string Text2 {get;set;}
}
public Parent()
{
Child = new Child();
Text = "I like pitfalls";
}