UNITTESTING · Teach Me Cool Stuff
How to Mock HttpContext
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