c# - 如何单元测试简单的属性有验证器集?

标签 c# unit-testing fluentvalidation

我对多个模型对象中的某些属性有类似的规则,我想用自定义属性验证器替换它们以避免单元测试中的代码重复。

我有我的属性验证器:

public class IntIdPropertyValidator: PropertyValidator
{
    public IntIdPropertyValidator()
        : base("Property {PropertyName} should be greater than 0")
    {
    }

    protected override bool IsValid(PropertyValidatorContext context)
    {
        var value = (int)context.PropertyValue;

        return value > 0;
    }
}

并将其连接到模型验证器类中:

public class SomeRequestValidator : AbstractValidator<CreateWordRequest>
{
    public SomeRequestValidator()
    {
        RuleFor(x => x.Id).SetValidator(new IntIdPropertyValidator());
    }
}

尝试测试:

[Test]
public void Validate_IdHasValidator_Success()
{
    Init();

    validator.ShouldHaveChildValidator(x => x.Id, typeof(IntIdPropertyValidator));
}

但是测试总是失败。

那么,我如何测试验证器是否实际设置为属性 Id?

最佳答案

您以错误的方式使用了 ShouldHaveChildValidatorId 是一个简单的类型。

ShouldHaveChildValidator正在用于复杂类型。 (另见 source code)

测试该属性的正确方法是传递有效对象和无效对象,然后使用 ShouldNotHaveValidationErrorFor 进行验证和 ShouldHaveValidationErrorFor :

[Test]
public void Should_have_error_when_Id_Is_Ilegal() {
      validator.ShouldHaveValidationErrorFor(p => p.Id, new CreateWordRequest());
}

[Test]
public void Should_not_have_error_when_Id_Is_Legal() {
      validator.ShouldNotHaveValidationErrorFor(p => p.Id, new CreateWordRequest()
                                                           {
                                                                Id = 7
                                                           });
}

编辑

以下代码将执行您正在寻找的验证:

[Test]
public void Validate_IdHasValidator_Success()
{
    var validator = new SomeRequestValidator();

    var descriptor = validator.CreateDescriptor();
    var matchingValidators = descriptor.GetValidatorsForMember(
                Extensions.GetMember<CreateWordRequest, int>(x => x.Id).Name);

    Assert.That(matchingValidators.FirstOrDefault(), Is.InstanceOf<IntIdPropertyValidator>());

}

我想向您解释一下您不应该使用上述代码的原因。

当你在 UT 上课时,你要验证类行为不会受到伤害。

当您创建自定义验证器时,您创建了一个负责验证特定模型(--> 业务规则)...

Id 是一个简单类型,根据其父模型具有业务规则。 因此需要通过模型验证器验证Id的业务规则。

假设您的其中一个模型突然需要更改。在这种情况下,您没有任何验证来证明您现有的任何业务规则都不会受到损害(或者您决定在 IntIdPropertyValidator 中进行更改,这样的举动会影响任何地方,即使您没有我不想)。

创建自定义 Property Validator 对代码维护非常有用,但是,测试应该针对模型验证器。

对于复杂类型,情况就完全不同了:

通常复杂类型都有自己的业务规则。在这种情况下,您必须为它们创建自定义验证器,然后验证父验证器是否使用了正确的验证器。还要验证的另一件事是:如果复杂类型为 Null 或复杂规则,例如“当属性值为 X 时,然后复杂类型状态为 Y”...

关于c# - 如何单元测试简单的属性有验证器集?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31089852/

相关文章:

c# - 我知道我做错了验证。请劝我停止 :)

c# - vb.net 重载解析失败,出现 "multiple members with this name exist in class"

javascript - 在 Angular 单元测试中,如何清理 $timeout promise ,以免它们持续存在?

c# - Mediatr 行为管道中的验证

c# - 将选定的行从数据 GridView 传输到另一个数据 GridView

unit-testing - 将模拟代码重构到另一个类中会导致 Spock 测试失败

python - 如何将 Django TestCases 收集到 TestSuites 中并运行它们?

c# - FluentValidation 不适用于外部模型对象的集合

c# - 如何将单元测试添加到我的流利验证类中?

c# - "only part of a readprocessmemory or writeprocessmemory request was completed"process.start 期间