Thursday, March 21, 2013

Testing an ASP.NET MVC Controller

I am a fan of testing my code and have been using SpecsFor, written by Matt Honeycutt, for a lot of my BDD-style unit testing lately. It makes testing very clear and easy to read, comes baked-in with Moq, StructureMap, and a whole lot more goodness.

One of the pain-points of testing ASP.NET MVC is dealing with the controller context, request, response, server, etc. So, I have extended SpecsFor a little bit for my controllers (in both F# and C#).

C#

namespace SpecsForExtensions
{
    using System;
    using System.Security.Principal;
    using System.Web;
    using System.Web.Mvc;
    using System.Web.Routing;

    public class ControllerSpecsFor<T> : DbSpecsFor<T>
        where T : Controller
    {
        protected override void InitializeClassUnderTest ()
        {
            base.InitializeClassUnderTest ();

            var context = GetMockFor<HttpContextBase> ();
            var session = GetMockFor<HttpSessionStateBase> ();
            var request = GetMockFor<HttpRequestBase> ();
            var response = GetMockFor<HttpResponseBase> ();
            var server = GetMockFor<HttpServerUtilityBase> ();
            var user = GetMockFor<IPrincipal> ();
            var identity = GetMockFor<IIdentity> ();
            var uri = new Uri ("http://localhost:12345");
            var requestContext = new RequestContext (context.Object, new RouteData ());

            context.Setup (x => x.Session).Returns (session.Object);
            context.Setup (x => x.Server).Returns (server.Object);
            context.Setup (x => x.Request).Returns (request.Object);
            context.Setup (x => x.Response).Returns (response.Object);
            context.Setup (x => x.User).Returns (user.Object);
            request.Setup (x => x.Url).Returns (uri);
            user.Setup (x => x.Identity).Returns (identity.Object);

            SUT.ControllerContext = new ControllerContext (context.Object, new RouteData (), SUT);
            SUT.Url = new UrlHelper (requestContext);
        }
    }
}

F#

namespace SpecsForExtensions

open System
open System.Security.Principal
open System.Web
open System.Web.Mvc
open System.Web.Routing
open SpecsFor

type ControllerSpecsFor<'a when 'a : not struct and 'a :> Controller>() =
    inherit SpecsFor<'a>()

    override this.InitializeClassUnderTest() =
        base.InitializeClassUnderTest()

        let context = this.GetMockFor<HttpContextBase>()
        let session = this.GetMockFor<HttpSessionStateBase>()
        let request = this.GetMockFor<HttpRequestBase>()
        let response = this.GetMockFor<HttpResponseBase>()
        let server = this.GetMockFor<HttpServerUtilityBase>()
        let user = this.GetMockFor<IPrincipal>()
        let identity = this.GetMockFor<IIdentity>()
        let uri = new Uri("http://localhost:1234")
        let requestContext = new RequestContext(context.Object, new RouteData())

        context.Setup<_>(fun x -> x.Session).Returns(session.Object) |> ignore
        context.Setup<_>(fun x -> x.Server).Returns(server.Object) |> ignore
        context.Setup<_>(fun x -> x.Request).Returns(request.Object) |> ignore
        context.Setup<_>(fun x -> x.Response).Returns(response.Object) |> ignore
        context.Setup<_>(fun x -> x.User).Returns(user.Object) |> ignore
        request.Setup<_>(fun x -> x.Url).Returns(uri) |> ignore
        user.Setup<_>(fun x -> x.Identity).Returns(identity.Object) |> ignore

        this.SUT.ControllerContext <- new ControllerContext (context.Object, new RouteData(), this.SUT)
        this.SUT.Url <- new UrlHelper(requestContext)

No comments:

Post a Comment