Mock HttpContext using Moq

In a project I’ve been working on, I needed a way to be able to test Windows authentication to an ASP MVC app. Having that authentication rest at the controller level made sense, but from a testing perspective it made things somewhat difficult. One aspect that wasn’t clear to me was mocking the HttpContext on the controller that controls the authentication checks. Especially since getting that setup to run correctly without using mocking, makes the test more of an integration test, rather than a unit test. Even though controllers are meant to be lean from a logic sense, being able to test the actions respond with the correct response given a set of parameters can be useful.

I wanted to share the mocked context I came up with and how to use it so that if you need to unit test your controller using Windows authentication, it’s that much easier. I’ve seen numerous people asking about mocking the User.Identity in the controller. This will explain how to do that.

I’m using Moq for my mocking. I don’t have a solid reason as to why I use it, just that’s what we’ve been using for our projects at the city so it’s what I learned to use. If you are using a different mocking framework, I’d love to hear about it.

Let’s get to it.

MockWebContext Class

I’ll go over it piece by piece. First, the class definition and the public properties:

The properties match the properties an HttpContext has. This way if we need to mock other aspects of it, we can. The most important one is the HttpContextBase (highlighted above). This is where the User object comes from that handles authentication.

Next, we are going to create two constructors. The first being the default constructor that just instantiates all the mocked properties:

We are really just mocking the various pieces of the HttpContext so that if any of them are accessed they return an empty mocked object. This is just to be used to test normal controller operations where authentication is not needed. Another place where you can do some cool things is with the Request object when doing tests. You can make the request return what you want to test malicious requests, malformed parameters, or other things.

Mocking Authentication

We need another constructor that will setup some authentication pieces. To explain it a little better, when doing Windows authentication, normally there’s a list of Active Directory groups/users added to the Web.config to limit access to certain people. In an ASP MVC controller, we can check if a user is in that list by doing:

The other method of checking a user’s authentication is the IsInRole method. This allows you to pass in the name of an Active Directory group and check if the user is in the group or not:

With that in mind, we will create a constructor that will setup these methods to create a HttpContext that can do fake authentication:

This constructor calls the default constructor to set everything up, and then it mocks out the methods I mentioned above. I set it up to allow multiple groups to be passed in if there are multiple checks that are made. You can change it to only be a single group if you wanted.

That’s the basics of creating a fake HttpContext. There’s one more piece that I added that’s not necessary, but have become useful. I added two static methods to the class that creates a controller context.

Using the Mock

So let’s see how to use our fake HttpContext on a controller so that we can go about testing them with and without authentication. Obviously you’ll need to mock out any other dependencies the controller may have, but having a mock HttpContext, the controller can be tested in isolation.

Let’s say I want to create a test class for my Home controller. This is how I could setup the tests:

If you wanted for a few actions to have some authentication happen, just change it in your test:

 Conclusion

That’s it. Mocking out that HttpContext is simple and I found it really useful to be able to test the authentication workflows that some of our controllers do.

If I did something wrong and you have a different method, I would love to hear about it.