Someone asked me a question recently about mocking, and I had to say I didn’t have much experience with it. I found this answer a bit odd myself as I’ve been doing a lot of TDD with an ASP.Net MVC application. I’d seen lots of people talking about mocking the HttpContext and wondered “Why haven’t I had to do this?”.

The first time I started TDD, I was working on converting an existing ASP.Net application to ASP.Net MVC. Most of my controller actions checked the current security principle in the context, so I immediately ran into problems when trying to test these.
I didn’t know much about MVC or TDD so used what I did know. I knew about a powerful component of MVC called an action invoker, that could be overridden to handle some parameter stuff. I found that I could easily create an ActionInvoker that would populate parameters of a certain type (namely IPrincipal) using the following code:
public class ActionInvoker : ControllerActionInvoker
{
   protected override object GetParameterValue(System.Reflection.ParameterInfo parameterInfo)
   {
      if (parameterInfo.ParameterType == typeof(IPrincipal))
         return HttpContext.Current.User;

      return base.GetParameterValue(parameterInfo);
   }
}

And put the following into my controller constructors:
public MyController()
{
   ActionInvoker = new ActionInvokers.ActionInvoker();
}
This made it easy to test my controller actions. I just needed to mock a simple IPrincipal. I used a similar solution when my file upload controller needed access to HttpContext.Current.Request.Files.
At the moment my code only depends on a few simple objects that come from the HttpContext and not the context itself. Surely this is better, if not please comment. I’m going to change the above to conform with everyone else by mocking the HttpContext but the only reason I see for doing this, is that the above action invoker is not testable. Is this the only reason?
Before you point it out to me, I have recently moved most of my security code into AuthorizeAttributes. Now my unit tests for invalid calls (security wise) to controller actions all fail but that’s for a future post.