4

FluentValidation.TestHelper 命名空间中的扩展方法 .ShouldHaveChildValidator() 没有采用模型的重载。然后,如何在使用 When() 子句时测试子验证器是否设置正确,如下例所示?

例如

public class ParentModel
{
    public bool SomeCheckbox { get; set; }

    public ChildModel SomeProperty { get; set; }
}

public class ParentModelValidator : AbstractValidator<ParentModel>
{
    RuleFor(m => m.SomeProperty)
            .SetValidator(new ChildModelValidator())
            .When(m => m.SomeCheckbox);
}

我想断言,如果 SomeCheckbox 为真,则子验证器存在,如果 SomeCheckbox 为假,则子验证器不存在。

到目前为止,我在单元测试中有以下内容:

ParentModelValidator validator = new ParentModelValidator();
validator.ShouldHaveChildValidator(
    m => m.SomeProperty, 
    typeof(ChildModelValidator));

但这没有考虑 .When() 条件。

我注意到 FluentValidation.TestHelper 命名空间中的其他方法,例如 .ShouldHaveValidationErrorFor() 具有采用模型的重载,因此通过设置满足先决条件的模型,很容易使用 When() 子句测试简单的属性类型。

有任何想法吗?

4

2 回答 2

2

这是我如何实现这一目标的片段:

public class ParentModelSimpleValidator : AbstractValidator<ParentModel>
{
    public ParentModelSimpleValidator()
    {
        When(x => x.HasChild, () =>
            RuleFor(x => x.Child)
                .SetValidator(new ChildModelSimpleValidator()));
    }
}

public class ChildModelSimpleValidator : AbstractValidator<ChildModel>
{
    public ChildModelSimpleValidator()
    {
        RuleFor(x => x.ChildName)
            .NotEmpty()
            .WithMessage("Whatever");
    }
}

以下是相关的简化模型:

[Validator(typeof(ParentModelSimpleValidator))]
public class ParentModel
{
    public bool HasChild { get { return Child != null; } }
    public ChildModel Child { get; set; }
}

[Validator(typeof(ChildModelSimpleValidator))]
public class ChildModel
{
    public string ChildName { get; set; }
    public int? ChildAge { get; set; }
}

这是一个示例单元测试:

[TestMethod]
public void ShouldValidateChildIfParentHasChild()
{
    var validator = new ParentModelSimpleValidator();

    var model = new ParentModel
    {
        ParentName = "AABBC",
        Child = new ChildModel { ChildName = string.Empty }
    };

    validator.ShouldHaveErrorMessage(model, "Whatever");
}
于 2012-12-20T09:51:06.707 回答
1

在这里玩游戏很晚,但我刚开始使用FluentValidation,这就是我的解决方案

  public class ParentValidator: AbstractValidator<ParentModel>
  {
    public ParentValidator()
    {
      // other rules here

      // use == for bool?
      When(model => model.SomeBoolProperty == false, () => RuleFor(model => model.ChildClass).SetValidator(new ChildClassValidator()));
    }
  }

  public class ChildClassValidator: AbstractValidator<ChildClass>
  {
    public ChildClassValidator()
    {
      this
        .RuleFor(model => model.SomeProperty).NotNull();
    }
  } 

那么测试是

[TestMethod]
public void ParentValidator_should_have_error_in_child_class_property_when_bool_is_false_on_parent()
{
  // Arrange - API does not support typical unit test
  var validator = new ParentValidator()
  var foo = new ParentModel() { SomeBoolProperty = false };
  foo.ChildClass.SomeProperty = null;

  // Act
  var result = validator.Validate(foo);

  // Assert - using FluentAssertions
  result.Errors.Should().Contain(err => err.PropertyName == "ChildClass.SomeProperty");
}
于 2015-04-08T17:35:06.087 回答