5

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

3 Answers 3

6

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.

Sign up to request clarification or add additional context in comments.

Comments

3

You can use:

_controller.Response.StatusCode

1 Comment

You do need to mock it first. For example by calling controller.SetMockControllerContext() from gist.github.com/johnnyreilly/4959924#file-mvcmockhelpers-cs.
3

Another option using MvcContrib's TestControllerBuilder...

var myController = new MyController();

var testControllerBuilder = new TestControllerBuilder();
testControllerBuilder.InitializeController(myController);

and then using NUnit (I'd guess the Moq version would work just like you have it)...

myController.Response.AssertWasCalled( response => response.StatusCode = 400 );

All the ugly setup and mocking work is still being done, but by MvcContrib instead of inside the test. Here's a post on using the TestControllerBuilder.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.