Home > DeveloperSection > Forums > How to do Unit tests on MVC validation
Goti Bandu

Total Post:119

Points:835
Posted on    November-21-2014 11:12 PM

 ASP.NET MVC Mvc4  Unit Testing  Validation 
Ratings:


 1 Reply(s)
 622  View(s)
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?



Jeet Verma
Jeet Verma

Total Post:110

Points:776
Posted on    November-22-2014 1:21 AM

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.


Don't want to miss updates? Please click the below button!

Follow MindStick