Hands on mocking of ASPNETMVC controller action

In this post, i will start with an MVC sample created from the default template project that is bundled with ASPNET MVC2 installation. This template provides not just a dummy project with folder organized but rather a full running app.The target of this post is to show a mocking of a controller action, in that regard i have picked  registration action chosen from the accounts controller of the provided sample that looks similar to:

  1. [HttpPost]
  2. public ActionResult Register(RegisterModel model)
  3. {
  4.     if (ModelState.IsValid)
  5.     {
  6.         // Attempt to register the user
  7.         MembershipCreateStatus createStatus = MembershipService.CreateUser(model.UserName, model.Password, model.Email);
  8.  
  9.         if (createStatus == MembershipCreateStatus.Success)
  10.         {
  11.             FormsService.SignIn(model.UserName, false /* createPersistentCookie */);
  12.             return RedirectToAction("Index", "Home");
  13.         }
  14.         else
  15.         {
  16.             ModelState.AddModelError("", AccountValidation.ErrorCodeToString(createStatus));
  17.         }
  18.     }
  19.  
  20.     // If we got this far, something failed, redisplay form
  21.     ViewData["PasswordLength"] = MembershipService.MinPasswordLength;
  22.     return View(model);
  23. }

Here the basic workflow that can be ensured for the target action are:

  • For valid status:
    • Creates the user with membership service.
    • Validates the create status.
    • On validating , signs in the user.
    • Returns to expected action.
  • For Invalid status:
    • Raises a model error.
  • Stores the password length.
  • Return;

Accordingly, to cover the first criteria that covers a valid registration.  We first created the accounts controller  and the registration model.

  1. AccountController controller = new AccountController();
  2. RegisterModel registerModel = new RegisterModel();

In order to validate model state, we also need to mock out the ModelStateDictionary  to set our expectation:

  1. var modelState = Mock.Create<ModelStateDictionary>();

Then, according to flow, we setup:

  1. Mock.Arrange(() => modelState.IsValid).Returns(true).MustBeCalled();
  2. Mock.Arrange(() => controller.ModelState).Returns(modelState);

Next, we need to pass out our custom MembershipService to the controller and  set it to return a valid response ignoring the arguments. We are ignoring the arguments, as here the specific argument is not important and we are concerned more with the desired step that should be completed.

  1. // mock membership service
  2. var membershipService = Mock.Create<IMembershipService>();
  3. Mock.Arrange(() => membershipService.CreateUser("", "", "")).IgnoreArguments()
  4.     .Returns(MembershipCreateStatus.Success).MustBeCalled();
  5. controller.MembershipService = membershipService;

Now, after having a successful registration our next goal is to make sure that developer has written the sign in code correctly and accordingly we do:

  1. // mock auth services
  2. var formsAuthService = Mock.Create<IFormsAuthenticationService>();
  3. Mock.Arrange(() => formsAuthService.SignIn("", false)).IgnoreArguments().MustBeCalled();
  4. controller.FormsService = formsAuthService;

 

To wrap it up and give a test run, we execute the controller with the RegisterModel  object that we have created previously.

  1. // act
  2. controller.Register(registerModel);

 

Finally, we make sure that required calls are made properly.

  1. // assert
  2. Mock.Assert(modelState);
  3. Mock.Assert(membershipService);
  4. Mock.Assert(formsAuthService);

 

Now, this is of a rough test, as you can see there are three different types of assert which should spun three different test methods. I left that to the reader :-).

 

P.S. This example is done using JustMock , by the time of writing this post IgnoreArguments() is still under its way to release[Justmock still in its beta]. The way shown for ignoring arguments can also be done using matcher, but it is to mention that for two or many arguments when we just want to ignore the whole chunk, using a modifier call is more elegant and cleaner to read.

2 Comments

  • Except the MembersipService and FormAuthentication none of the class needs to mocked/stubbed. RegisterModel, ModelStateDictionary are POCO classes which does not depends on anything that are hard to create in tests.

  • Yes you are right, updated the RegisterModel. But for ModelStateDictionary, i need to verify that dev has called it. Ideally, it should not be in the same flow rather have a separte method, but as i said. I left out to reader and its just a rough example :-).

Comments have been disabled for this content.