HOW TO DO UNIT TESTS ON MVC VALIDATION

Goti Bandu

Total Post:119

Points:835
Posted by  Goti Bandu
 1010  View(s)
Ratings:
Rate this:

How can I test that my controller action is putting the correct errors in the ModelState when validating an entity, when I'm using DataAnnotation validation in MVC 2 Preview 1?

Some code to illustrate. First, the action:

    [HttpPost]

    public ActionResult Index(BlogPost b)

    {

        if(ModelState.IsValid)

        {

            _blogService.Insert(b);

            return(View("Success", b));

        }

        return View(b);

    }

And here's a failing unit test that I think should be passing but isn't (using 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);

}

I guess in addition to this question, should I be testing validation, and should I be testing it in this way?

  1. Jeet Verma

    Post:110

    Points:776
    Re: How to do Unit tests on MVC validation

    Instead of passing in a BlogPost you can also declare the actions parameter as FormCollection. Then you can create the BlogPost yourself and call UpdateModel(model, formCollection.ToValueProvider());. This will trigger the validation for any field in the 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);

        }

    Just make sure your test adds a null value for every field in the views form that you want to leave empty.

    I found that doing it this way, at the expense of a few extra lines of code, makes my unit tests resemble the way the code gets called at runtime more closely making them more valuable. Also you can test what happens when someone enters "abc" in a control bound to an int property.

Answer

NEWSLETTER

Enter your email address here always to be updated. We promise not to spam!