Mocking Request.IsAjaxRequest()
Recently I was tasked with investigating Controller testing within our ASP.NET MVC apps. Our applications typically use a lot of jQuery AJAX calls to controller methods. To prevent users manually typing the URLs, the first thing that is done in any controller method that is called using AJAX is a check to see if Request.IsAjaxRequest() is true.
In order to properly test these ActionMethods we need to set the Controllers ControllerContext using a mocked HttpContextBase object that will return true for IsAjaxRequest(). To do this I created an extension method for the Controller class which uses the Moq .NET mocking library.
Since IsAjaxRequest() is an extension method we can’t just set it to return true, instead we need to set the “X-Requested-With” request header with a value of “XMLHttpRequest” to signify that it is an AJAX call. This is set using the WebHeaderCollection class and HttpRequestBase class.
The following code is the extension method:
using System.Net;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Moq;
public static void MakeAjaxRequest(this Controller controller)
{
// First create request with X-Requested-With header set
Mock<HttpRequestBase> httpRequest = new Mock<HttpRequestBase>();
httpRequest.SetupGet(x => x.Headers).Returns(
new WebHeaderCollection() {
{"X-Requested-With", "XMLHttpRequest"}
}
);
// Then create contextBase using above request
Mock<HttpContextBase> httpContext = new Mock<HttpContextBase>();
httpContext.SetupGet(x => x.Request).Returns(httpRequest.Object);
// Set controllerContext
controller.ControllerContext = new ControllerContext(httpContext.Object, new RouteData(), controller);
}
Using this in a test method would look something like:
[TestMethod]
public void CreateGET_ReturnsCorrectView()
{
MyController controller = new MyController();
controller.MakeAjaxRequest();
PartialViewResult result = (PartialViewResult)controller.Create(1);
Assert.AreEqual("Create", result.ViewName);
}