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!

2 Answers 2

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

Sign up to request clarification or add additional context in comments.

2 Comments

I just read something like this here: thepursuitofquality.com/post/53/… 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.
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.
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

2 Comments

Yes I am using DataAnnotations. I cannot see how to invoke UpdateModel in the test. Is that what you mean?
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.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.