Some of the actions that we are writing in Asp.Net MVC contains logic which uses data from the User context eg. user authentication or user name. Controller base class contains User property which is the instance of  IPrincipal with two important properties.

User.Identity.Name
User.Identity.IsAuthenticated

The IPrincipal is taken from the HttpContext

    public IPrincipal User
    {
      get
      {
        if (this.HttpContext != null)
          return this.HttpContext.User;
        else
          return (IPrincipal) null;
      }
    }

So if your action is using the User  property directly (you can always wrap this property inside a class that implements mockable Interface ) there is a problem with unit testing. In a isolated enviroment like test case , Controller doesn’t have the HttpContext. It is an external dependency.

HttpContext is retrieved from the ControllerContext

    public HttpContextBase HttpContext
    {
      get
      {
        if (this.ControllerContext != null)
          return this.ControllerContext.HttpContext;
        else
          return (HttpContextBase) null;
      }
    }

In order to fake the User property First we need to create a fake  ControllerContext. To create it we need  HttpContext  which also needs HttpRequest.  User is created from IPrincipal and IIdentity , with those classes we can create a Stub inside the HttpContext.

Yep , It’s quite complicated. Fortunately MvcContrib Library helps a little by providing classes that are faking IIdentity and IPrincipal

If you want to create a fake user you just need to write

When creating FakeIdentity userName parametr is really important. If you want ,not authenticated user , pass Empty String as a parameter

Yey , it’s the end ! Check out this simple graph.

image

Using this information , I have implemented simple TestHelper with methods to generate Fake ControlleContext with faked User.

  public static class TestHelper
    {
        public static ControllerContext MockControllerContext(Controller controller)
        {
            var httpContext = MockRepository.GenerateMock<HttpContextBase>();
            var httpRequest = MockRepository.GenerateMock<HttpRequestBase>();
            httpContext.Stub(x => x.Request).Return(httpRequest);
            return new ControllerContext(httpContext,new RouteData(),controller);
        }

        public static ControllerContext WithAuthenticatedUser(this ControllerContext context, string userName)
        {
            var user = new FakePrincipal(new FakeIdentity(userName),null);
            context.HttpContext.Stub(x => x.User).Return(user);
            return new ControllerContext(context.HttpContext,new RouteData(),context.Controller);
        }

        public static ControllerContext WithNotAuthenticatedUser(this ControllerContext context)
        {
            var user = new FakePrincipal(new FakeIdentity(String.Empty), null);
            context.HttpContext.Stub(x => x.User).Return(user); 
            return new ControllerContext(context.HttpContext, new RouteData(), context.Controller);
        }
}

Usage:

ProfileController.ControllerContext =
TestHelper.MockControllerContext(ProfileController).WithAuthenticatedUser("test");

Hope this sample helps.