I am trying to write a unit test for my one controller to verify if a view was returned properly, but this controller has a basecontroller that accesses the HttpContext.Current.Session. Everytime I create a new instance of my controller is calls the basecontroller constructor and the test fails with a null pointer exception on the HttpContext.Current.Session. Here is the code:
public class BaseController : Controller { protected BaseController() { ViewData["UserID"] = HttpContext.Current.Session["UserID"]; } } public class IndexController : BaseController { public ActionResult Index() { return View("Index.aspx"); } } [TestMethod] public void Retrieve_IndexTest() { // Arrange const string expectedViewName = "Index"; IndexController controller = new IndexController(); // Act var result = controller.Index() as ViewResult; // Assert Assert.IsNotNull(result, "Should have returned a ViewResult"); Assert.AreEqual(expectedViewName, result.ViewName, "View name should have been {0}", expectedViewName); }
Any ideas on how to mock (using Moq) the Session that is accessed in the base controller so the test in the descendant controller will run?
Mock HTTPContext using DefaultHttpContext Please use the DefaultHttpContext object to set up a mock version of the HttpContext in the controller. var httpContext = new DefaultHttpContext(); Set up the custom header used 'X-Custom-Header', httpContext.
ControllerContext(HttpContextBase, RouteData, ControllerBase) Initializes a new instance of the ControllerContext class by using the specified HTTP context, URL route data, and controller.
Unless you use Typemock or Moles, you can't.
In ASP.NET MVC you are not supposed to be using HttpContext.Current. Change your base class to use ControllerBase.ControllerContext - it has a HttpContext property that exposes the testable HttpContextBase class.
Here's an example of how you can use Moq to set up a Mock HttpContextBase:
var httpCtxStub = new Mock<HttpContextBase>(); var controllerCtx = new ControllerContext(); controllerCtx.HttpContext = httpCtxStub.Object; sut.ControllerContext = controllerCtx; // Exercise and verify the sut
where sut
represents the System Under Test (SUT), i.e. the Controller you wish to test.
If you are using Typemock, you can do this:
Isolate.WhenCalled(()=>controller.HttpContext.Current.Session["UserID"]) .WillReturn("your id");
The test code will look like:
[TestMethod] public void Retrieve_IndexTest() { // Arrange const string expectedViewName = "Index"; IndexController controller = new IndexController(); Isolate.WhenCalled(()=>controller.HttpContext.Current.Session["UserID"]) .WillReturn("your id"); // Act var result = controller.Index() as ViewResult; // Assert Assert.IsNotNull(result, "Should have returned a ViewResult"); Assert.AreEqual(expectedViewName, result.ViewName, "View name should have been {0}", expectedViewName); }
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With