Mat*_*ves 75 validation tdd asp.net-mvc unit-testing asp.net-mvc-2
当我在MVC 2预览1中使用DataAnnotation验证时,如何在验证实体时测试我的控制器操作是否在ModelState中放置了正确的错误?
一些代码来说明.一,行动:
[HttpPost]
public ActionResult Index(BlogPost b)
{
if(ModelState.IsValid)
{
_blogService.Insert(b);
return(View("Success", b));
}
return View(b);
}
Run Code Online (Sandbox Code Playgroud)
这是一个失败的单元测试,我认为应该通过但不是(使用MbUnit和Moq):
[Test]
public void When_processing_invalid_post_HomeControllerModelState_should_have_at_least_one_error()
{
// arrange
var mockRepository = new Mock<IBlogPostSVC>();
var homeController = new HomeController(mockRepository.Object);
// act
var p = new BlogPost { Title = "test" }; // date and content should be required
homeController.Index(p);
// assert
Assert.IsTrue(!homeController.ModelState.IsValid);
}
Run Code Online (Sandbox Code Playgroud)
我想除了这个问题,应该我来测试验证,并应在我这种方式测试它?
小智 192
讨厌一个老帖子,但我想我会添加自己的想法(因为我刚遇到这个问题并且在寻找答案时遇到了这个帖子).
你真正想要测试的是你的控制器在验证失败时按照你的期望做.这是你的代码,也是你的期望.一旦你意识到你想要测试的全部内容,就很容易进行测试:
[test]
public void TestInvalidPostBehavior()
{
// arrange
var mockRepository = new Mock<IBlogPostSVC>();
var homeController = new HomeController(mockRepository.Object);
var p = new BlogPost();
homeController.ViewData.ModelState.AddModelError("Key", "ErrorMessage"); // Values of these two strings don't matter.
// What I'm doing is setting up the situation: my controller is receiving an invalid model.
// act
var result = (ViewResult) homeController.Index(p);
// assert
result.ForView("Index")
Assert.That(result.ViewData.Model, Is.EqualTo(p));
}
Run Code Online (Sandbox Code Playgroud)
Gil*_*ith 87
我遇到了同样的问题,在阅读了Pauls的回答和评论后,我找到了一种手动验证视图模型的方法.
我发现本教程解释了如何手动验证使用DataAnnotations的ViewModel.他们的密钥代码片段即将发布.
我稍微修改了代码 - 在教程中省略了TryValidateObject的第4个参数(validateAllProperties).为了将所有注释都设置为Validate,应将其设置为true.
另外,我将代码重构为通用方法,使ViewModel验证的测试变得简单:
public static void ValidateViewModel<TViewModel, TController>(this TController controller, TViewModel viewModelToValidate)
where TController : ApiController
{
var validationContext = new ValidationContext(viewModelToValidate, null, null);
var validationResults = new List<ValidationResult>();
Validator.TryValidateObject(viewModelToValidate, validationContext, validationResults, true);
foreach (var validationResult in validationResults)
{
controller.ModelState.AddModelError(validationResult.MemberNames.FirstOrDefault() ?? string.Empty, validationResult.ErrorMessage);
}
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,这对我们来说非常有效.
在测试中调用homeController.Index方法时,您没有使用任何触发验证的MVC框架,因此ModelState.IsValid将始终为true.在我们的代码中,我们直接在控制器中调用辅助程序Validate方法,而不是使用环境验证.我没有太多使用DataAnnotations的经验(我们使用NHibernate.Validators)也许其他人可以提供如何从控制器中调用Validate的指导.
Mau*_*ice -4
BlogPost您也可以将 actions 参数声明为 ,而不是传入 a FormCollection。然后您可以自己创建BlogPost并调用UpdateModel(model, formCollection.ToValueProvider());.
这将触发对FormCollection.
[HttpPost]
public ActionResult Index(FormCollection form)
{
var b = new BlogPost();
TryUpdateModel(model, form.ToValueProvider());
if (ModelState.IsValid)
{
_blogService.Insert(b);
return (View("Success", b));
}
return View(b);
}
Run Code Online (Sandbox Code Playgroud)
只需确保您的测试为视图表单中要留空的每个字段添加一个空值即可。
我发现这样做,以几行额外的代码为代价,使我的单元测试更类似于在运行时调用代码的方式,从而使它们更有价值。您还可以测试当有人在绑定到 int 属性的控件中输入“abc”时会发生什么。
| 归档时间: |
|
| 查看次数: |
23206 次 |
| 最近记录: |