Monday 7 January 2013

Unit Testing HttpContext.Current.Session in MVC3 .NET

We recently changed some functionality where during the "CREATE" process, we go through a wizard to save application data. This data is saved only to the session in the final step when the user clicks the final submit.

This was easy enough to implement but when I started writing unit tests for my static methods that Add, Update, Delete or Modify the contents of our application data in the session, I got the following error:

System.NullReferenceException: Object reference not set to an instance of an object.


Turns out I had forgotten to setup the HttpContext.

The following "TestInitialise" method fixed my problem :)

 
[TestInitialize]
public void TestSetup()
{
    // We need to setup the Current HTTP Context as follows:            

    // Step 1: Setup the HTTP Request
    var httpRequest = new HttpRequest("", "http://localhost/", "");

    // Step 2: Setup the HTTP Response
    var httpResponce = new HttpResponse(new StringWriter());

    // Step 3: Setup the Http Context
    var httpContext = new HttpContext(httpRequest, httpResponce);
    var sessionContainer = 
        new HttpSessionStateContainer("id", 
                                       new SessionStateItemCollection(),
                                       new HttpStaticObjectsCollection(), 
                                       10, 
                                       true,
                                       HttpCookieMode.AutoDetect,
                                       SessionStateMode.InProc, 
                                       false);
    httpContext.Items["AspSession"] = 
        typeof(HttpSessionState)
        .GetConstructor(
                            BindingFlags.NonPublic | BindingFlags.Instance,
                            null, 
                            CallingConventions.Standard,
                            new[] { typeof(HttpSessionStateContainer) },
                            null)
        .Invoke(new object[] { sessionContainer });

    // Step 4: Assign the Context
    HttpContext.Current = httpContext;
}
 
[TestMethod]
public void BasicTest_Push_Item_Into_Session()
{
    // Arrange
    var itemValue = "RandomItemValue";
    var itemKey = "RandomItemKey";
            
    // Act
    HttpContext.Current.Session.Add(itemKey, itemValue);
            
    // Assert
    Assert.AreEqual(HttpContext.Current.Session[itemKey], itemValue);
}



References: http://stackoverflow.com/questions/9624242/setting-the-httpcontext-current-session-in-unit-test

5 comments:

  1. Great post man!. made my day today... thank you.

    ReplyDelete
  2. Finally! This was just the post I needed. With all the dozens of posts on StackOverflow, they also forget about HttpContext. This nailed it on the head. Now I can get some actual work done today. :-)

    ReplyDelete
  3. FYI: These are the namespaces I needed ..
    using System.IO;
    using System.Web;
    using System.Web.SessionState;
    using System.Reflection;
    using Microsoft.VisualStudio.TestTools.UnitTesting;

    ReplyDelete
  4. Great ! You really saved my day.
    Thanks a lot.

    ReplyDelete