Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit Testing Controller Actions that call IsAjaxRequest()

Some of my controller actions need to respond with different ViewResults depending whether or not they were called by an AJAX request. Currently, I'm using the IsAjaxRequest() method to check for this. When this method is called during a unit test, it throws an ArgumentNullException because the HTTP context is missing.

Is there a way to mock/fake this call? Or is this a sign I should be checking for an AJAX request another way?

like image 283
Kirschstein Avatar asked Dec 11 '09 18:12

Kirschstein


2 Answers

Would it help if you provide a Test Double for the HTTP Context?

This can be done like this:

var httpCtxStub = new Mock<HttpContextBase>();

var controllerCtx = new ControllerContext();
controllerCtx.HttpContext = httpCtxStub.Object;

sut.ControllerContext = controllerCtx;

where sut represents the System Under Test (SUT), i.e. the Controller you wish to test.

This example uses Moq.

like image 141
Mark Seemann Avatar answered Nov 17 '22 16:11

Mark Seemann


Using moq library in MVC test projects

[TestClass]
public class HomeControllerTest
{
    [TestMethod]
    public void Index()
    {
        // Arrange
        HomeController controller = new HomeController();
        controller.injectContext();
        // controller.injectContext(ajaxRequest: true);

        // Act
        ViewResult result = controller.Index() as ViewResult;

        // Assert
        Assert.IsNotNull(result);
    }
}


public static class MvcTestExtensions
{
    public static void injectContext(this ControllerBase controller, bool ajaxRequest = false)
    {
        var fakeContext = new Mock<ControllerContext>();
        fakeContext.Setup(r => r.HttpContext.Request["X-Requested-With"])
            .Returns(ajaxRequest ? "XMLHttpRequest" : "");
        controller.ControllerContext = fakeContext.Object;
    }
}
like image 5
Ghominejad Avatar answered Nov 17 '22 16:11

Ghominejad