ModelState.IsValid不验证模型

时间:2012-01-20 02:22:59

标签: c# asp.net-mvc-3

我的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);
        }

我错过了什么吗? 提前谢谢。

3 个答案:

答案 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                
        }