我的Model类如下:
public class PostInputViewModel
{
[Required]
[MinLength(1)]
[MaxLength(125)]
public string Title { get; set; }
[Required]
[AllowHtml]
[Display(Name="Content")]
public string Content { get; set; }
}
和控制器如下:
[HttpPost]
public ActionResult Write(PostInputViewModel input)
{
if (!ModelState.IsValid)
return View(input);
var post = new Post
{
Title = input.Title,
Content = input.Content,
DateCreated = DateTime.Now,
DateModified = DateTime.MaxValue,
};
dbContext.Posts.Add(post);
dbContext.SaveChanges();
return RedirectToAction("Index", "Home");
}
当我通过单击F5运行Web应用程序时,如果我没有输入标题和内容值,则ModelState.IsValid为false,但是如果我使用单元测试用例测试控制器类,则ModelState.IsValid始终为true。测试用例如下:
[TestMethod]
public void write_should_validate_model()
{
var input = new PostInputViewModel();
input.Title = null;
input.Content = null;
var actionResult = controller.Write(input) as ViewResult;
Assert.IsFalse(actionResult.ViewData.ModelState.IsValid);
}
我错过了什么吗? 提前谢谢。
答案 0 :(得分:9)
如果您想让控制器尝试验证模型,可以在断言之前调用TryValidateModel
方法:
controller.TryValidateModel(input);
但我同意你真的只是在测试验证属性。不过可能没问题;它将验证您的模型是否已应用预期属性。
答案 1 :(得分:4)
控制器中不会发生模型验证。它在模型传递给控制器之前发生。
请注意,控制器操作仅“测试”模型是否有效。谁在您的测试用例中验证模型?没有!
您可以使用Validator类.NET进行验证,但在这种情况下,您将测试.NET验证。这是人们在编写单元测试时常犯的错误之一。他们测试第三方代码而不是他们自己的代码。
如果你真的想测试你已经将正确的验证属性应用到类中,那么你可以简单地反映你的类并检查属性的属性。这样您就可以跳过.NET验证层,只有在错过属性时,测试才会失败。
答案 2 :(得分:4)
验证实际上是在调用控制器上的Write方法之前发生的,它会填充ModelState属性。
在我看来,你的单元测试并没有真正测试控制器(如果那是你想要做的事情)。
真正的控制器测试看起来像这样:
[TestMethod]
public void write_should_validate_model()
{
controller.ModelState.AddModelError("Title", "Empty"); //These values don't really matter
var actionResult = controller.Write(new PostInputViewModel()) as ViewResult;
//Assert that the correct view was returned i.e. Not Home/Index
//Assert that a new post has not been added to your Mock Repository
}