3

I have a very simple scenario:

[HttpGet]
public ActionResult CreateUser()
{
    return View();
}

[HttpGet]
public ActionResult Thanks()
{
    return View();
}

[HttpPost]
public ActionResult CreateUser(CreateUserViewModel CreateUserViewModel)
{
    if (ModelState.IsValid)
    {
    return View("Thanks");
    }

    return View(CreateUserViewModel);
}

My unit test uses the testhelper from mvc contrib:

[Test]
public void UserController_CannotCreateUserWithNoLastName()
{
    // arrange
    UsersController UsersController = new UsersController();
    CreateUserViewModel CreateUserViewModel = new CreateUserViewModel();
    CreateUserViewModel.LastName = "";

    // act
    ActionResult result = UsersController.CreateUser(CreateUserViewModel);

    // assert
    result.AssertViewRendered().ForView("CreateUser");
}

When I open the browser and try to submit an invalid user (no lastname) it redirects to the createuser form but the unit test fails (it says that it redirects to thanks). Why is this? Can anyone see anything wrong? Thanks!

cs0815
  • 16,751
  • 45
  • 136
  • 299

2 Answers2

7

Inside your unit test you should simulate that your model has an error because it's what you want to test (the error path). In your test the model is valid that's why it redirects you to the "Thanks" view. To simulate the error you can do that in your unit test before "act" section :

UsersController.ModelState.AddModelError("username", "Bad username"); 

Take a look on that example : http://www.thepursuitofquality.com/post/53/how-to-test-modelstateisvalid-in-aspnet-mvc.html

More about AddModelError method here : http://msdn.microsoft.com/en-us/library/system.web.mvc.modelstatedictionary.addmodelerror.aspx

Tomasz Jaskuλa
  • 15,723
  • 5
  • 46
  • 73
  • I just read something like this here: http://www.thepursuitofquality.com/post/53/how-to-test-modelstateisvalid-in-aspnet-mvc.html I have to admit that I do not fully understand. Basically I do not need to create an invalid viewmodel and just add this error to test that the controller reacts appropriately. Is this right? But how do I test that the controller copes correctly with invalid view models? Thanks. – cs0815 Jun 22 '11 at 10:58
  • 1
    What you want to test is the logic in your action. One unit test for the ModelState.IsValid == true and another one when the ModelState.IsValid == false. For the second test you should simulate that there was an error in your model. When the application runs, the validation of the model happens upfront to the execution of your action. Youd don't have that validation in the unit test because you're not running all the ASP.NET MVC framework. That's why you should simulate an error in your model to test only your logic in action. ASP.NET MVC team has already tested the validation pipline. – Tomasz Jaskuλa Jun 22 '11 at 11:47
3

I beleive you are using DataAnnotations for LastName empty so validation will be performed by the ModelBinder. Unit test will skip ModelBinder and validation.

See this SO question for more details - call UpdateModel on the Controller manually

Community
  • 1
  • 1
swapneel
  • 3,061
  • 1
  • 25
  • 32
  • Yes I am using DataAnnotations. I cannot see how to invoke UpdateModel in the test. Is that what you mean? – cs0815 Jun 22 '11 at 13:30
  • Validation will be performed by the ModelBinder so if you call updatemodel - validaion will be perfomed on your viewmodel and respective errors will be added to the model. – swapneel Jun 23 '11 at 09:30