Proxy classes for HttpContext and related objects, based on Phil Haack's blog post but without the 3rd party DuckTyping library that was causing massive failures in my production environment.
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
HttpInterfaces
nuget
.gitignore
HttpInterfaces.sln
README.markdown

README.markdown

HttpInterfaces provides interfaces to wrap HttpContext and other unmockable, abstract base classes that you might use in your controllers and model binders on an ASP.NET MVC project.

For example, in the following code, you would not be able write a unit test for this code because you don't have an actual HttpContext:

public class OrderController
{
	public ActionResult Index()
	{
		Session["foo"] = "bar";
		var productName = Request.Form["Product_3_Name"];
	}
}

You can try to use partial mocks, create derived classes, and implement abstract classes in order to make these things testable, but everyone I know who has tried eventually gets frustrated or runs into something they can't fake out in a test. So just save yourself the trouble and use the interfaces instead.

You get the following interfaces:

ICache - Cache
IHttpApplication - HttpApplication
IHttpApplicationState - HttpApplicationState
IHttpCachePolicy - CachePolicy
IHttpClientCertificate - HttpClientCertificate
IHttpContext - HttpContext
IHttpFileCollection - HttpFileCollection
IHttpModuleCollection - HttpModuleCollection
IHttpRequest - HttpRequest
IHttpResponse - HttpResponse
IHttpServerUtility - HttpServerUtility
IHttpSession - System.Web.SessionState.HttpSessionState
ITraceContext - TraceContext

You can configure a DI container like StructureMap to use the interfaces like this:

ObjectFactory.Initialize(x =>
{
    x.For<IHttpApplication>().Use(
        c => WebContext.Cast(HttpContext.Current.ApplicationInstance));
    x.For<IHttpApplicationState>().Use(
        c => WebContext.Cast(HttpContext.Current.Application));
    x.For<IHttpCachePolicy>().Use(
        c => WebContext.Cast(HttpContext.Current.Response.Cache));
    x.For<IHttpClientCertificate>().Use(
        c => WebContext.Cast(HttpContext.Current.Request.ClientCertificate));
    x.For<IHttpContext>().Use(
        c => WebContext.Cast(HttpContext.Current));
    x.For<IHttpFileCollection>().Use(
        c => WebContext.Cast(HttpContext.Current.Request.Files));
    x.For<IHttpModuleCollection>().Use(
        c => WebContext.Cast(HttpContext.Current.ApplicationInstance.Modules));
    x.For<IHttpRequest>().Use(
        c => WebContext.Cast(HttpContext.Current.Request));
    x.For<IHttpResponse>().Use(
        c => WebContext.Cast(HttpContext.Current.Response));
    x.For<IHttpServerUtility>().Use(
        c => WebContext.Cast(HttpContext.Current.Server));
    x.For<IHttpSession>().Use(
        c => WebContext.Cast(HttpContext.Current.Session));
    x.For<ITraceContext>().Use(
        c => WebContext.Cast(HttpContext.Current.Trace));
}

Now you can take these interfaces into your controllers as constructor parameters:

public class OrderController
{
	private IHttpSession _session;
	private IHttpRequest _request;
	
	public OrderController(IHttpSession session, IHttpRequest request)
	{
		_session = session;
		_request = request;
	}
	
	public ActionResult Index()
	{
		_session["foo"] = "bar";
		var productName = _request.Form["Product_3_Name"];
	}
}

I can easily test these controller methods because I can stub out the interfaces in my tests.

This was originally inspired by this blog post by Phil Haack. In Phil's post, he uses a library that dynamically generates the interfaces. I ran into some problems with the library that did this... it sometimes would throw an exception generating the interface code and I would have to restart IIS. So I spent the 20 minutes that it took to create the interfaces and implement the proxy classes by hand.

Installation

Easiest way to install is to use nuget.

 Install-Package HttpInterfaces

Have fun!