驱魔少年缇亚调教:How To Test ModelState.IsValid In ASP.NET MVC | RANDOMTYPE Inc.

来源:百度文库 编辑:九乡新闻网 时间:2024/04/29 14:35:52

How To Test ModelState.IsValid In ASP.NET MVC

| Written by Gavin Miller


When you encounter the problem of writing tests for ModelState.IsValidfor the first time it can be very frustrating, especially because ModelBinding doesn’t work in unit tests. This article details how to writeunit tests against a controller calling ModelState.IsValid.

Let’s set the scene. You’re testing a controller that you’ve built – the AddController. And you’re testing the Add action for that controller. In the code there are two paths through the controller.

  1. If the ModelState is valid, the “Added” View is called
  2. If the ModelState is invalid, the “Add” View is called

The code looks like this:

public class AddController {     public ActionResult Add(ModelObject model)     {         if (!ModelState.IsValid)             return View("Add");           // Code to perform Add         return View("Added");     } }

And the code for testing an invalid model:

[Test] public void InvalidModelObject_ShouldReturnAddView() {     var expectedViewName = "Add";     var controller = new AddController();       var model = ModelObject.InvalidModelObject();     var result = controller.Add(model) as ViewResult;       Assert.AreEqual(expectedViewName, result.ViewName); }

The above code attempts to pass a ModelObject to the Add action and cause the !ModelState.IsValid to return false.

When running through a web page, this is done automatically withModel Binding. But running with unit tests you will quickly came across aproblem; running within a unit testing context, Model Binding doesn’t work! And believe it or not, that’s exactly how Model Binding should work because there’s a problem with this code.

Have you spotted it? This code isn’t testing the controller. It’stesting the Model Binding. And that’s a waste of time because Microsoftalready tested Model Binding before they shipped ASP.NET MVC!

Having ModelState.IsValid equate to true or false is aside effect of Model Binding. However tests should be written so thatthey’re free from side effects. So relying on Model Binding to set ModelState.IsValid as a side effect is wrong.

How do you test ModelState.IsValid?

So what’s the right way to test ModelState.IsValid in unit tests? The correct way to test ModelState.IsValid is by adding a ModelState error to the controller, before the action is called.

[Test] public void InvalidModelState_ShouldReturnAddView() {     var expectedViewName = "Add";     var controller = new AddController();       // Causes ModelState.IsValid to return false     controller.ModelState.AddModelError("key", "model is invalid");       var model = ModelObject.InvalidModelObject();     var result = controller.Add(model) as ViewResult;       Assert.AreEqual(expectedViewName, result.ViewName); }

By calling AddModelError you’re setting ModelState.IsValid to false, because the ModelState has an error. This successfully exercises your test case and makes it clear for anyone reading the test what is being tested.