How to Mock HttpContext

Code making direct calls to Asp.Net's HttpContext can be tricky to test since HttpContext is not fully defined in the scope of a unit test. In this article I will demonstrate how to get around this issue by mocking the context and some of its common properties.

I will use a simple tax calculation function to show how to seamlessly mock the call to retrieve the sales tax from HttpSession.

Code listing 1 shows my MVC controller.

public class SalesController : Controller { public SalesController():this(new ControllerContext()){} public SalesController(ControllerContext ctx) { this.ControllerContext = ctx; } [HttpGet] public ActionResult CalculatePrice(double priceBeforeTax) { double salesTax = (double)this.ControllerContext.HttpContext.Session["SalesTax"]; double priceAfterTax = priceBeforeTax + (priceBeforeTax * salesTax / 100.0); return View(priceAfterTax); } }
Code listing 1

Normally we would have a problem here if we tried to unit test this method since we would get a "not implemented exception" due to the undefined Session object.

The solution is to introduce mocking of HttpContext and Session: In my example I will use a popular mocking framework called MOQ.

Code listing 2 shows my unit test with mocked values for the session backed sales tax:

[Test] public void WillReturnPriceAfterTaxes() { Mock httpContext = new Mock<HttpContextBase>(); Mock session = new Mock<HttpSessionStateBase>(); session.Setup(s => s["SalesTax"]).Returns(4.0); httpContext.Setup(c => c.Session).Returns(session.Object); ControllerContext ctx = new ControllerContext(); ctx.HttpContext = httpContext.Object; SalesController controller = new SalesController(ctx); ViewResult v = controller.CalculatePrice(10) as ViewResult; Assert.AreEqual(10.4, v.Model); }
Code listing 2