Search code examples
c#asp.net-mvc-3unit-testingmoqmspec

How to test HTTP status code set by an ASP.NET MVC action with MSpec


I have the following controller:

public sealed class SomeController : Controller
{
    public ActionResult PageNotFound()
    {
        Response.StatusCode = 404;

        return View("404");
    }
}

I have created an MSpec specification:

[Subject(typeof (SomeController))]
public class when_invalid_page_is_requested : SomeControllerSpec
{
    Because of = () => result = Controller.PageNotFound();

    It should_set_status_code_to_404 = 
        () => Controller.Response.StatusCode.ShouldEqual(404);
}

public abstract class SomeControllerSpec
{
    protected static HomeController Controller;

    Establish context = () => { Controller = new SomeController(); };
}

But because of how I instantiate the controller, HttpContext is null. What would be the best way to test status code set by the PageNotFound action?

EDIT: Posted an answer below


Solution

  • Found a way to do it using Moq.

    [Subject(typeof (SomeController))]
    public class when_invalid_page_is_requested : SomeControllerSpec
    {
        Because of = () => result = Controller.PageNotFound();
    
        It should_set_status_code_to_404 = 
            () => HttpResponse.VerifySet(hr => hr.StatusCode = 404);
    }
    
    public abstract class SomeControllerSpec
    {
        protected static SomeController Controller;
        protected static Mock<ControllerContext> ControllerContext;
        protected static Mock<HttpResponseBase> HttpResponse;
    
        Establish context = () =>
        {
            ControllerContext = new Mock<ControllerContext>();
            HttpResponse = new Mock<HttpResponseBase>();
            ControllerContext.SetupGet(cc => cc.HttpContext.Response)
                             .Returns(HttpResponse.Object);
    
            Controller = new SomeController
                             {
                                 ControllerContext = ControllerContext.Object
                             };
        };
    }
    

    Not very elegant. If you can think of a better way - let me know.