[英]NullReference exception throw by FluentValidation when mocking child validators
Starting with something simple:从简单的事情开始:
public interface IChild
{
string Value { get; }
}
public class ChildValidator : AbstractValidator<IChild>
{
public ChildValidator()
{
RuleFor(c => c.Value)
.NotEmpty()
.NotEmpty()
.WithMessage("Friendly Error Message");
}
}
And then testing it:然后测试一下:
static void Test_ChildValidator()
{
var child = Substitute.For<IChild>();
var validator = new ChildValidator();
child.Value.Returns(null as string);
validator.Validate(child).IsValid.Should().BeFalse();
child.Value.Returns("");
validator.Validate(child).IsValid.Should().BeFalse();
child.Value.Returns("a");
validator.Validate(child).IsValid.Should().BeTrue();
}
No Exceptions .没有例外。
Create a parent object and validator:创建一个父对象和验证器:
public interface IParent
{
IChild Child { get; }
}
public class ParentValidator : AbstractValidator<IParent>
{
public ParentValidator(IValidator<IChild> childValidator)
{
When(p => p.Child != null, () => {
RuleFor(p => p.Child)
.SetValidator(childValidator);
});
}
}
Then test that with a real child validator:然后用一个真正的子验证器测试它:
static void Test_ParentValidator_WithRealChildValidator()
{
var child = Substitute.For<IChild>();
var childValidator = new ChildValidator();
var parent = Substitute.For<IParent>();
var validator = new ParentValidator(childValidator);
parent.Child.Returns(null as IChild);
validator.Validate(parent).IsValid.Should().BeTrue();
parent.Child.Returns(child);
validator.Validate(parent).IsValid.Should().BeFalse();
child.Value.Returns("a");
validator.Validate(parent).IsValid.Should().BeTrue();
}
No Exceptions.没有例外。
Now I tried to Mock the Child Validator (Eventually I just want to make sure that when the Child object is null or is not null, the child validator Validate
method is or isn't called).现在我尝试模拟子验证器(最终我只想确保当 Child 对象为 null 或不为 null 时,是否调用了子验证器Validate
方法)。
static void Test_ParentValidator_WithMockedChildValidator()
{
var child = Substitute.For<IChild>();
var childValidator = Substitute.For<IValidator<IChild>>();
var parent = Substitute.For<IParent>();
var validator = new ParentValidator(childValidator);
parent.Child.Returns(null as IChild);
validator.Validate(parent).IsValid.Should().BeTrue();
parent.Child.Returns(child);
childValidator.Validate(Arg.Any<IChild>())
.Returns(
new ValidationResult(
new List<ValidationFailure> { new ValidationFailure("property", "message") }));
validator.Validate(parent).IsValid.Should().BeFalse();
childValidator.Validate(Arg.Any<IChild>())
.Returns(new ValidationResult());
validator.Validate(parent).IsValid.Should().BeTrue();
}
Throws a NullReferenceException
抛出NullReferenceException
Source: "FluentValidation"来源:“FluentValidation”
StackTrace:堆栈跟踪:
at FluentValidation.Validators.ChildValidatorAdaptor.Validate(PropertyValidatorContext context) in在 FluentValidation.Validators.ChildValidatorAdaptor.Validate(PropertyValidatorContext context) 中
/home/jskinner/code/FluentValidation/src/FluentValidation/Validators/ChildValidatorAdaptor.cs:line 56 /home/jskinner/code/FluentValidation/src/FluentValidation/Validators/ChildValidatorAdaptor.cs:line 56
at FluentValidation.Internal.PropertyRule.InvokePropertyValidator(ValidationContext context, IPropertyValidator validator, String propertyName) in在 FluentValidation.Internal.PropertyRule.InvokePropertyValidator(ValidationContext context, IPropertyValidator validator, String propertyName) 中
/home/jskinner/code/FluentValidation/src/FluentValidation/Internal/PropertyRule.cs:line 442 /home/jskinner/code/FluentValidation/src/FluentValidation/Internal/PropertyRule.cs:line 442
at FluentValidation.Internal.PropertyRule.d__65.MoveNext()在 FluentValidation.Internal.PropertyRule.d__65.MoveNext()
in /home/jskinner/code/FluentValidation/src/FluentValidation/Internal/PropertyRule.cs:line 282在 /home/jskinner/code/FluentValidation/src/FluentValidation/Internal/PropertyRule.cs:line 282
at System.Linq.Enumerable.SelectManySingleSelectorIterator`2.MoveNext()在 System.Linq.Enumerable.SelectManySingleSelectorIterator`2.MoveNext()
at System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()在 System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()
at FluentValidation.AbstractValidator
1.Validate(ValidationContext
1 context) in在 FluentValidation.AbstractValidator1.Validate(ValidationContext
1 context) 中/home/jskinner/code/FluentValidation/src/FluentValidation/AbstractValidator.cs:line 115 /home/jskinner/code/FluentValidation/src/FluentValidation/AbstractValidator.cs:line 115
at FluentValidation.AbstractValidator`1.Validate(T instance) in /home/jskinner/code/FluentValidation/src/FluentValidation/AbstractValidator.cs:line 83在 FluentValidation.AbstractValidator`1.Validate(T instance) in /home/jskinner/code/FluentValidation/src/FluentValidation/AbstractValidator.cs:line 83
at SubValidationTest.Program.Test_ParentValidator_WithMockedChildValidator()在 SubValidationTest.Program.Test_ParentValidator_WithMockedChildValidator()
Is there something else I need to mock on the mocked validator to make this work correctly?我还需要在模拟验证器上模拟其他东西才能使其正常工作吗?
pastebin - full source code pastebin - 完整的源代码
I was not able to get this code working (at all) on DotNetFiddle :(我无法让这段代码在 DotNetFiddle 上工作(根本):(
From the stack trace it looks like it fails on从堆栈跟踪看来它失败了
FluentValidation.AbstractValidator1.Validate(ValidationContext1 context)
which was not one of the member configured on the mock.这不是模拟上配置的成员之一。
This should behave as expected这应该按预期运行
[TestMethod]
public void Test_ParentValidator_WithMockedChildValidator() {
var child = Substitute.For<IChild>();
var childValidator = Substitute.For<IValidator<IChild>>();
var parent = Substitute.For<IParent>();
var validator = new ParentValidator(childValidator);
parent.Child.Returns(null as IChild);
validator.Validate(parent).IsValid.Should().BeTrue();
parent.Child.Returns(child);
var failedResult = new ValidationResult(new List<ValidationFailure> { new ValidationFailure("property", "message") });
childValidator.Validate(Arg.Any<ValidationContext>()).Returns(failedResult);
validator.Validate(parent).IsValid.Should().BeFalse();
var validResult = new ValidationResult();
childValidator.Validate(Arg.Any<ValidationContext>()).Returns(validResult);
validator.Validate(parent).IsValid.Should().BeTrue();
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.