单元测试 ASP.NET DataAnnotations 验证
我正在使用 DataAnnotations 进行模型验证,即
[Required(ErrorMessage="Please enter a name")]
public string Name { get; set; }
在我的控制器中,我正在检查 ModelState 的值。对于从我看来发布的无效模型数据,这正确地返回 false。
但是,在执行控制器操作的单元测试时,ModelState 始终返回 true:
[TestMethod]
public void Submitting_Empty_Shipping_Details_Displays_Default_View_With_Error()
{
// Arrange
CartController controller = new CartController(null, null);
Cart cart = new Cart();
cart.AddItem(new Product(), 1);
// Act
var result = controller.CheckOut(cart, new ShippingDetails() { Name = "" });
// Assert
Assert.IsTrue(string.IsNullOrEmpty(result.ViewName));
Assert.IsFalse(result.ViewData.ModelState.IsValid);
}
我需要做任何额外的事情来在测试中设置模型验证吗?
I am using DataAnnotations for my model validation i.e.
[Required(ErrorMessage="Please enter a name")]
public string Name { get; set; }
In my controller, I am checking the value of ModelState. This is correctly returning false for invalid model data posted from my view.
However, when executing the unit test of my controller action, ModelState always returns true:
[TestMethod]
public void Submitting_Empty_Shipping_Details_Displays_Default_View_With_Error()
{
// Arrange
CartController controller = new CartController(null, null);
Cart cart = new Cart();
cart.AddItem(new Product(), 1);
// Act
var result = controller.CheckOut(cart, new ShippingDetails() { Name = "" });
// Assert
Assert.IsTrue(string.IsNullOrEmpty(result.ViewName));
Assert.IsFalse(result.ViewData.ModelState.IsValid);
}
Do I need to do anything extra to set up the model validation in my tests?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
我在 我的博客文章:
I posted this in my blog post:
验证将由 ModelBinder 执行。在示例中,您自己构造
ShippingDetails
,这将跳过ModelBinder
,从而完全跳过验证。请注意输入验证和模型验证之间的区别。输入验证是为了确保用户提供了一些数据,前提是他有机会这样做。如果您提供的表单没有关联字段,则不会调用关联的验证器。MVC2 中的模型验证与输入验证发生了变化,因此确切的行为取决于您使用的版本。请参阅 http:// bradwilson.typepad.com/blog/2010/01/input-validation-vs-model-validation-in-aspnet-mvc.html 有关 MVC 和 MVC 2 的详细信息。
[编辑] 我猜最干净的解决方案是在测试时通过提供自定义模拟
ValueProvider
手动调用 Controller 上的UpdateModel
。这应该会触发验证并正确设置 ModelState 。Validation will be performed by the
ModelBinder
. In the example, you construct theShippingDetails
yourself, which will skip theModelBinder
and thus, validation entirely. Note the difference between input validation and model validation. Input validation is to make sure the user provided some data, given he had the chance to do so. If you provide a form without the associated field, the associated validator won't be invoked.There have been changes in MVC2 on model validation vs. input validation, so the exact behaviour depends on the version you are using. See http://bradwilson.typepad.com/blog/2010/01/input-validation-vs-model-validation-in-aspnet-mvc.html for details on this regarding both MVC and MVC 2.
[EDIT] I guess the cleanest solution to this is to call
UpdateModel
on the Controller manually when testing by providing a custom mockValueProvider
. That should fire validation and set theModelState
correctly.我正在浏览 http://bradwilson.typepad.com /blog/2009/04/dataannotations-and-aspnet-mvc.html,在这篇文章中,我不喜欢将验证测试放在控制器测试中以及在每个测试中手动检查是否验证属性存在或不存在。因此,下面是我实现的辅助方法及其用法,它适用于 EDM(具有元数据属性,因为我们无法在自动生成的 EDM 类上应用属性)和将 ValidationAttributes 应用于其属性的 POCO 对象。
辅助方法不会解析为分层对象,但可以在平面单个对象(类型级别)上测试验证,
这是另一篇文章 http://johan.driessen.se/archive/2009/11/18/testing-dataannotation-based-validation -in-asp.net-mvc.aspx 讨论了在 .Net 4 中进行验证,但我想我将坚持使用在 3.5 和 4 中都有效的辅助方法
I was going through http://bradwilson.typepad.com/blog/2009/04/dataannotations-and-aspnet-mvc.html, in this post I didn't like the idea of putting the validation tests in controller test and somewhat manual checking in each test that if the validation attribute exists or not. So, below is the helper method and it's usage which I implemented, it works for both EDM (which has metadata attributes, because of the reason we can not apply attributes on auto generated EDM classes) and POCO objects which have ValidationAttributes applied to their properties.
The helper method does not parse into hierarchical objects, but validation can be tested on flat individual objects(Type-level)
this is another post http://johan.driessen.se/archive/2009/11/18/testing-dataannotation-based-validation-in-asp.net-mvc.aspx which talks about validating in .Net 4, but i think i am going to stick to my helper method which is valid in both 3.5 and 4
我喜欢在控制器上下文之外测试模型和视图模型的数据属性。我通过编写自己的 TryUpdateModel 版本来完成此操作,该版本不需要控制器,并且可用于填充 ModelState 字典。
这是我的 TryUpdateModel 方法(主要取自 .NET MVC 控制器源代码):
然后可以在单元测试中轻松使用它,如下所示:
I like to test the data attributes on my models and view models outside the context of the controller. I've done this by writing my own version of TryUpdateModel that doesn't need a controller and can be used to populate a ModelState dictionary.
Here is my TryUpdateModel method (mostly taken from the .NET MVC Controller source code):
This can then be easily used in a unit test like this:
我遇到了一个问题,TestsHelper 大部分时间都可以工作,但不适用于 IValidatableObject 接口定义的验证方法。 CompareAttribute 也给我带来了一些问题。这就是为什么 try/catch 在那里。以下代码似乎验证了所有情况:
I had an issue where TestsHelper worked most of the time but not for validation methods defined by the IValidatableObject interface. The CompareAttribute also gave me some problems. That is why the try/catch is in there. The following code seems to validate all cases: