如何调用验证属性进行测试?
我正在使用 DataAnnotations 中的 RegularExpressionAttribute 进行验证,并想测试我的正则表达式。有没有办法在单元测试中直接调用该属性?
我希望能够做类似的事情:
public class Person
{
[RegularExpression(@"^[0-9]{3}-[0-9]{3}-[0-9]{4}$")]
public string PhoneNumber { get; set; }
}
然后在单元测试中:
[TestMethod]
public void PhoneNumberIsValid
{
var dude = new Person();
dude.PhoneNumber = "555-867-5309";
Assert.IsTrue(dude.IsValid);
}
或者甚至
Assert.IsTrue(dude.PhoneNumber.IsValid);
I am using the RegularExpressionAttribute from DataAnnotations for validation and would like to test my regex. Is there a way to invoke the attribute directly in a unit test?
I would like to be able to do something similar to this:
public class Person
{
[RegularExpression(@"^[0-9]{3}-[0-9]{3}-[0-9]{4}$")]
public string PhoneNumber { get; set; }
}
Then in a unit test:
[TestMethod]
public void PhoneNumberIsValid
{
var dude = new Person();
dude.PhoneNumber = "555-867-5309";
Assert.IsTrue(dude.IsValid);
}
Or even
Assert.IsTrue(dude.PhoneNumber.IsValid);
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我最终使用了 DataAnnotations 命名空间中的静态 Validator 类。我的测试现在看起来像这样:
I ended up using the static Validator class from the DataAnnotations namespace. My test now looks like this:
只需新建一个 RegularExpressionAttribute 对象即可。
Just new up a RegularExpressionAttribute object.
抱歉回复晚了。
我是新来的。如果您想测试隔离中的每个 ValidationAttribute,您可以继续执行下一种方式,例如:
Sorry for answering late.
I'm new here. If you want test every ValidationAttribute in isolate you can proceed to the next manner for example:
我使用了 @Martin 的建议以及静态常量文件,这使我可以避免在本地指定正则表达式字符串
I used the @Martin 's suggestion along with a static constants file which allowed me to avoid specifing the regex string locally
您可以使用此类来验证隔离中的任何 ValidationAttribute 类型:
T = 包含属性的类类型,
A = 类型 ValidationAttribute
示例:
You can use this class for validate any ValidationAttribute type in isolate:
T = class type containing the property,
A = type ValidationAttribute
Example:
在 @Evelio 的答案的基础上,我将提供一个关于如何对自定义验证器进行单元测试的答案,因为这似乎在互联网上的任何地方都没有阐明,并且这是在搜索如何做时出现的热门点击之一它。
@Evelio 的答案非常接近,但还需要更多的解释。
要测试验证,您需要一个将验证属性附加到其成员数据的类。在这里,我使用了一个新的自定义验证器,它对我的项目有意义,称为 FeeTimeUnitValidator。该验证器采用一个范围和另一个属性作为输入。如果其他属性为零,则验证器附加到的属性并不重要。但如果另一个属性不为零,则该属性需要在范围内。
这是我用于测试的 MockClass:
注意属性验证:
这表示检查属性“Fee”作为 Fee 属性(即,它必须非零),然后范围为 1 - 12。
我实例化类在单元测试类中并使用设置方法进行设置。由于此类上有三个具有验证器的属性,因此我将属性的名称传递到设置类中。
有一些有趣的事情。我正在使用 @Evelio 的方法从属性中提取验证器。这是设置例程的第 3 行和第 4 行中的内容。然后,由于这是一个单元测试方法,我做了一些断言以确保我得到了我所期望的结果。当我将此模式转移到另一个验证器的另一个单元测试类时,这实际上遇到了一个问题。
然后另一个关键是我创建 ValidationContext (因为更复杂的验证器需要一个上下文来查找它们引用的其他属性 - 在我的例子中,我使用它来查找 Fee 属性)。当我研究如何对这些自定义验证器进行单元测试时,让我困惑的是 ValidationContext。我找不到任何有关如何创建它们的信息。我相信属性验证的“上下文”是属性所在的类。这就是为什么我使用类实例作为第一个参数创建验证上下文。然后,这为验证器提供了对类上其他属性的访问权限,以便您可以进行跨属性验证。
现在我已经创建了上下文和指向验证器的指针,我可以跳入单元测试本身以确保验证器正确完成其工作:
如果我的验证器不需要上下文(即,它可以验证属性)不引用其他属性),那么我可以使用更简单的 IsValid() 接口,但如果验证器需要非空上下文,则必须使用 GetValidationResult() 方法,就像我在这里所做的那样。
我希望这对那些可能正在编写验证器并且像我一样热衷于单元测试的人有所帮助。 :)
这是一篇关于创建自定义验证器的好文章。
Building on @Evelio's answer I am going to provide an answer to how do you unit test custom validators since this doesn't seem to be articulated anywhere on the internet and this is one of the top hits that come up when searching for how to do it.
@Evelio's answer is very close, but it could do with a bit more of an explanation.
To test your validation you need to have a class that attaches validation attributes to its member data. Here I am using a new custom validator that makes sense for my project called FeeTimeUnitValidator. This validator takes a range and another attribute as input. If the other attribute is zero, then the attribute the validator is attached to doesn't matter. But if the other attribute is not zero, then this attribute needs to be in the range.
Here is the MockClass I use for testing:
Notice the attribute validation:
This says to check the property "Fee" as the Fee property (i.e., it has to be non-zero) and then the range is 1 - 12.
I instantiate class in the unit test class and set it up with a setup method. Since there are three attributes on this class that have the validator, I pass in the name of the attribute into the setup class.
There are a few things of interest. I am using @Evelio's approach to extract the validator from the attribute. This is doe in lines 3 and 4 of the setup routine. Then, since this is a unit test method, I do some asserts to make sure that I got what I expected. This actually caught a problem when I transferred this pattern to another unit test class for another validator.
Then the other key is that I create the ValidationContext (since the more complicated validators need a context to find the other attributes they refer to - in my case I use it to find the Fee attribute). When I was researching how to unit test these custom validators, what was tripping me up was the ValidationContext. I couldn't find any information about how to create them. I believe the "context" for the attribute validation is the class in which the attribute lives. This is why I create the validation context with the class instance as the first parameter. This then provides the validator with access to the other attributes on the class so you can do cross attribute validation.
Now that i have the context created and a pointer to a validator, I can jump into the unit test itself to ensure that the validator is doing its job properly:
If my validator didn't need a context (i.e., it could validate the attribute without reference to the other attributes), then I could use the simpler interface of IsValid(), but if the validator needs a non-null context, you have to use the GetValidationResult() method like I have done here.
I hope this helps somebody else who might be writing validators and is as religious about unit testing as I am. :)
Here is a good article on creating custom validators.
扩展@CobraGeek的答案和@Erik的评论,您可以使用
Validator.TryValidateProperty
来仅验证一个字段而不是整个对象,如下所示: >result 是表示验证成功的布尔值,如果为 false,
results
包含抛出的错误的详细信息列表。Extending on @CobraGeek's answer and @Erik's comment, you can use the
Validator.TryValidateProperty
to validate only that one field instead of the whole object, as so:After which
result
is the boolean indicating success of the validation, and if falseresults
contains the list of the details of the errors thrown.