title: Mocking Session not working in MVC 5
body: <p>I'm storing values in the Session in my controller Action being tested.  I've read several articles on how to mock a session and I'm trying to implement Milox's answer to <a href="https://stackoverflow.com/questions/9624242/setting-the-httpcontext-current-session-in-unit-test/10126711#10126711">Setting the httpcontext current session in unit test</a>.  But when I drill into <code>Locals | this | base | HttpContext</code> <code>Sessions</code> is still null and the test fails with a Null Reference exception when setting the Session variable <code>HttpContext.Session["BsAcId"] = vM.BusAcnt.Id;</code></p>
  
  <p>This is working production code.  <code>vM.BusAcnt.Id</code> returns a valid <code>int</code> and if I substitute it with an <code>int</code> value the test still fails because the <code>Session</code> is null and therefore no value can be stored in it.</p>
  
  <p>I'm using MVC5, EF6, and the latest versions of xUnit, Moq and the Resharper test runner.</p>
  
  <p>Action:</p>
  
  <pre><code>public ActionResult Details(int id)
  {
    var vM = new BusAcntVm();
    vM.BusAcnt = _db.BusAcnts.FirstOrDefault(bA =&gt; bA.Id == id);
  
    if ((User.IsInRole("Admin"))) return RedirectToAction("Action");
  
    HttpContext.Session["BsAcId"] = vM.BusAcnt.Id;
  
    return View(vM);
  }
  </code></pre>
  
  <p>MockHelpers:</p>
  
  <pre><code>  public static class MockHelpers
    {
      public static HttpContext FakeHttpContext()
      {
        var httpRequest = new HttpRequest("", "http://localhost/", "");
        var stringWriter = new StringWriter();
        var httpResponce = new HttpResponse(stringWriter);
        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 });
  
        return httpContext;
      }
    }
  </code></pre>
  
  <p>Test:</p>
  
  <pre><code>[Fact] 
  public void AdminGetBusAcntById()
  {
    HttpContext.Current = MockHelpers.FakeHttpContext();
    var mockMyDb = MockDbSetup.MockMyDb();
    var controller = new BusAcntController(mockMy.Object);
    var controllerContextMock = new Mock&lt;ControllerContext&gt;();
    controllerContextMock.Setup( x =&gt; x.HttpContext.User.
      IsInRole(It.Is&lt;string&gt;(s =&gt; s.Equals("Admin")))).Returns(true);
    controller.ControllerContext = controllerContextMock.Object;
  
    var viewResult = controller.Details(1) as ViewResult;
    var model = viewResult.Model as BusAcntVm;
  
    Assert.NotNull(model);
    Assert.Equal("Company 1", model.CmpnyName);
  }
  </code></pre>
  
  <p>Milox's code seems to make sense but I can't get it to work.
  Have  I missed something?  Is there a change in MVC5 that breaks this code?</p>
  
  <p><strong>SOLUTION:</strong></p>
  
  <p>Implementation of Darin's answer.  I now have a Session to write the values against (though the values don't actually get written into it, but that's not needed for the purpose of testing) and the test passes.</p>
  
  <p>Test:</p>
  
  <pre><code>[Fact] 
  public void AdminGetBusAcntById()
  {
    var mockMyDb = MockDbSetup.MockMyDb();
    var controller = new BusAcntController(mockMy.Object);
    var context = new Mock&lt;HttpContextBase&gt;();
    var session = new Mock&lt;HttpSessionStateBase&gt;();
    var user = new GenericPrincipal(new GenericIdentity("fakeUser"), new[] { "Admin" });
    context.Setup(x =&gt; x.User).Returns(user);
    context.Setup(x =&gt; x.Session).Returns(session.Object);
    var requestContext = new RequestContext(context.Object, new RouteData());
    controller.ControllerContext = new ControllerContext(requestContext, controller);
  
  
    var viewResult = controller.Details(1) as ViewResult;
    var model = viewResult.Model as BusAcntVm;
  
    Assert.NotNull(model);
    Assert.Equal("Company 1", model.CmpnyName);
  }
  </code></pre>