如何使用FluentValidation.TestHelper对具有When()条件的子验证器进行单元测试

时间:2012-01-26 12:36:26

标签: asp.net-mvc-3 fluentvalidation

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

E.g。

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为true,则存在子验证器,如果SomeCheckbox为false,则子验证器不存在。

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

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

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

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

有什么想法吗?

2 个答案:

答案 0 :(得分: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");
}

答案 1 :(得分: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");
}