繁体   English   中英

模拟子验证器时 FluentValidation 抛出 NullReference 异常

[英]NullReference exception throw by FluentValidation when mocking child validators

从简单的事情开始:

public interface IChild
{
  string Value { get; }
}

public class ChildValidator : AbstractValidator<IChild>
{
  public ChildValidator()
  {
    RuleFor(c => c.Value)
      .NotEmpty()
      .NotEmpty()
      .WithMessage("Friendly Error Message");
  }
}

然后测试一下:

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();
}

没有例外

创建一个父对象和验证器:

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);
    });
  }
}

然后用一个真正的子验证器测试它:

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();
}

没有例外。

现在我尝试模拟子验证器(最终我只想确保当 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();
}

抛出NullReferenceException

来源:“FluentValidation”

堆栈跟踪:

在 FluentValidation.Validators.ChildValidatorAdaptor.Validate(PropertyValidatorContext context) 中

/home/jskinner/code/FluentValidation/src/FluentValidation/Validators/ChildValidatorAdaptor.cs:line 56

在 FluentValidation.Internal.PropertyRule.InvokePropertyValidator(ValidationContext context, IPropertyValidator validator, String propertyName) 中

/home/jskinner/code/FluentValidation/src/FluentValidation/Internal/PropertyRule.cs:line 442

在 FluentValidation.Internal.PropertyRule.d__65.MoveNext()

在 /home/jskinner/code/FluentValidation/src/FluentValidation/Internal/PropertyRule.cs:line 282

在 System.Linq.Enumerable.SelectManySingleSelectorIterator`2.MoveNext()

在 System.Linq.Enumerable.WhereEnumerableIterator`1.MoveNext()

在 FluentValidation.AbstractValidator 1.Validate(ValidationContext 1 context) 中

/home/jskinner/code/FluentValidation/src/FluentValidation/AbstractValidator.cs:line 115

在 FluentValidation.AbstractValidator`1.Validate(T instance) in /home/jskinner/code/FluentValidation/src/FluentValidation/AbstractValidator.cs:line 83

在 SubValidationTest.Program.Test_ParentValidator_WithMockedChildValidator()

我还需要在模拟验证器上模拟其他东西才能使其正常工作吗?

pastebin - 完整的源代码

我无法让这段代码在 DotNetFiddle 上工作(根本):(

从堆栈跟踪看来它失败了

 FluentValidation.AbstractValidator1.Validate(ValidationContext1 context)

这不是模拟上配置的成员之一。

这应该按预期运行

[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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM