如何unit testing简单属性有validation器设置?
我对多个模型对象中的某些属性有类似的规则,我想用自定义属性validation器替换它们,以避免unit testing中的代码重复。
我有我的财产validation人:
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; } }
并在模型validation器类中连接它:
public class SomeRequestValidator : AbstractValidator { public SomeRequestValidator() { RuleFor(x => x.Id).SetValidator(new IntIdPropertyValidator()); } }
试图测试:
[Test] public void Validate_IdHasValidator_Success() { Init(); validator.ShouldHaveChildValidator(x => x.Id, typeof(IntIdPropertyValidator)); }
但是测试总是失败。
那么,我如何测试实际为属性Id设置的validation器?
您正在以错误的方式使用ShouldHaveChildValidator
。 Id
是一种简单的类型。
ShouldHaveChildValidator正在复杂类型中使用。 (另见源代码 )
测试属性的正确方法是传递有效对象和无效对象,然后使用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 }); }
编辑
以下代码将执行您要查找的validation:
[Test] public void Validate_IdHasValidator_Success() { var validator = new SomeRequestValidator(); var descriptor = validator.CreateDescriptor(); var matchingValidators = descriptor.GetValidatorsForMember( Extensions.GetMember(x => x.Id).Name); Assert.That(matchingValidators.FirstOrDefault(), Is.InstanceOf()); }
我想解释一下你不应该使用上述代码的原因。
当您使用UT类时,您将validation类行为是否不会受到损害。
创建自定义validation程序时,您将创建一个负责validation特定模型( – >业务规则)的类…
Id
是一种简单类型,根据其父模型具有业务规则。 因此,您需要通过模型validation程序validationId
的业务规则。
让我们假设你的一个模型突然需要改变。 在这种情况下,您没有任何validation任何现有业务规则不会受到损害(或者您决定在IntIdPropertyValidator
进行更改,这样的移动会影响任何地方,即使您不想这样做)。
创建自定义Property Validator
非常适合代码维护,但是测试应该针对模型validation器。
在复杂类型上,故事完全不同:
通常,复杂类型有自己的业务规则。 在这种情况下,您必须为它们创建自定义validation器,然后validation父validation器使用正确的validation器。 要validation的另一件事是:如果复杂类型是Null
或复杂的规则,例如“当属性值为X然后复杂类型状态为Y”时……