CodeBetter.Com
CodeBetter.Com
RSS 2.0 via Feedburner
           Do you Twitter? Follow us @CodeBetter

Jeffrey Palermo (.com)

Blog moved to www.jeffreypalermo.com

Break the dependency on HttpContext in order to test web functionality - level 300

HttpContext.Current is very useful, and it's easy to sprinkle website code with it.  The bad side effect is that code that calls HttpContext.Current cannot be run in a test harness.  This is a big problem.  This post will show how to test code that needs HttpContext.Current.

The key is to break the dependency on HttpContext.Current.  By breaking the dependency, we can run our code in a test harness (like NUnit) and verify that it's working correct (test harnesses are also great for debugging).  To start breaking the dependency, consider the following code we have:

        public string GetLoggedInUserName()
        {
            return HttpContext.Current.User.Identity.Name;
        }

This code dives right into the ASP.NET API, and code that depends on this method will be impossible to test.  To break this dependency on HttpContext.Current, we have to know what we really need.  We need the user name of the currently logged in user.  We are pulling this from the IPrincipal object.  We're going to strip out this code and put an interface in it's place:

    [PluginFamily("Default")]
    public interface ICurrentHttpContext
    {
        IPrincipal Principal { get;}
    }  

Next, we need to have a way for the original class to find a class that implements this interface for runtime.  We'll use StructureMap for the dirt-simple linking through attributes:

    [Pluggable("Default")]
    public class CurrentHttpContext : ICurrentHttpContext
    {
        public IPrincipal Principal
        {
            get { return HttpContext.Current.User; }
        }
    }

Now we need to modify the original class with a testing constructor and a default constructor for dependency discovery:

    public class MyThingy
    {
        ICurrentHttpContext _context;
 
        public MyThingy(ICurrentHttpContext context)
        {
            _context = context;
        }
 
        public MyThingy()
        {
            _context = (ICurrentHttpContext) ObjectFactory.GetInstance(typeof(ICurrentHttpContext));
        }
 
        public string GetLoggedInUserName()
        {
            return _context.Principal.Identity.Name;
        }

    }

Notice here that we have a default constructor that asks StructureMap for the right implementation of ICurrentHttpContext, and for a unit test we have the constructor that accepts a mock instance.  This example shows that it is very easy to break a dependency on HttpContext.Current.  We can continue to use the fantastic services of HttpContext.Current while keeping our codebase testable. 



Comments

Gary Williams said:

Jeremy had a post related to this on his blog: http://codebetter.com/blogs/jeremy.miller/archive/2006/01/10/136407.aspx which might be of interest to anyone looking at this.
# January 19, 2006 10:51 PM

About Jeffrey Palermo

Jeffrey Palermo is a software management consultant and the CTO of Headspring Systems in Austin, TX. Jeffrey specializes in Agile coaching and helps companies double the productivity of software teams. Jeffrey is an MCSD.Net , Microsoft MVP, Certified Scrummaster, Austin .Net User Group leader, AgileAustin board member, INETA speaker, INETA Membership Mentor, Christian, husband, father, motorcyclist, Eagle Scout, U.S. Army Veteran, and Texas A&M University graduate. Check out Devlicio.us!

This Blog

Syndication

News

Headspring Systems

View Jeffrey Palermo's profile on LinkedIn

See my new blog at .jeffreypalermo.com