Skip to content

Moq and MvcMockHelpers

I’m working on some unit tests for an ASP.NET MVC application I’m developing.  One of the tests ensures that if I construct a URL using Html.ActionLink that the URL which is returned, when fed into the routing system, becomes a correct representation of the route data used to build the URL originally.  I’ll discuss this further in a future post, but today I’m going to talk about Moq. Unfortunately, this type of testing requires more mocking than you’d really prefer, despite the significant improvements in unit-testability in recent previews of the ASP.NET MVC framework.

I started with the MvcMockHelpers library released by Scott Haselman.  It does quite a bit of what I need, so that saved me a lot of work.  Scott’s library supports three different mocking frameworks; of these, I chose Moq.

My tests hit some areas of the HttpContext which Scott’s mock didn’t implement, so I set out to extend it.  One bit, HttpContextBase.ApplyAppPathModifier, was a bit more challenging to mock, despite the fact that the result I needed was quite simple: The mocked function should simply return its only argument.  The Moq demos don’t cover this case, although it is a supported feature in the 2.0 version. After a little digging around through the forums and the change logs, I figured out how to do it:

response.Expect(res => res.ApplyAppPathModifier(It.IsAny<string>()))
    .Returns((string virtualPath) => virtualPath);

There are two parts to this.  First, you specify that this mock will match a call to ApplyAppPathModifier with any string argument.  That is the It.IsAny bit.  Inside the Returns call is a lambda expression which specifies how to turn a string argument into a result.  In this case, the expression is very simple.

So, for anyone who wants it, here is my current implementation of the FakeHttpContext() method.  It returns a mocked HttpContext which is good enough for the unit testing I’m doing at the moment.

        public static HttpContextBase FakeHttpContext()
        {
            var context = new Mock<HttpContextBase>();
            var request = new Mock<HttpRequestBase>();
            var response = new Mock<HttpResponseBase>();
            var session = new Mock<HttpSessionStateBase>();
            var server = new Mock<HttpServerUtilityBase>();
            var user = new Mock<IPrincipal>();
            var identity = new Mock<IIdentity>();

            request.Expect(req => req.ApplicationPath).Returns("~/");
            request.Expect(req => req.AppRelativeCurrentExecutionFilePath).Returns("~/");
            request.Expect(req => req.PathInfo).Returns(string.Empty);
            response.Expect(res => res.ApplyAppPathModifier(It.IsAny<string>()))
                .Returns((string virtualPath) => virtualPath);
            user.Expect(usr => usr.Identity).Returns(identity.Object);
            identity.ExpectGet(ident => ident.IsAuthenticated).Returns(true);

            context.Expect(ctx => ctx.Request).Returns(request.Object);
            context.Expect(ctx => ctx.Response).Returns(response.Object);
            context.Expect(ctx => ctx.Session).Returns(session.Object);
            context.Expect(ctx => ctx.Server).Returns(server.Object);
            context.Expect(ctx => ctx.User).Returns(user.Object);

            return context.Object;
        }

{ 2 } Comments

  1. Abner | September 17, 2011 at 12:26 am | Permalink

    I would like to appreciate the work you’ve made in writing this publish. It has been an inspiration for me personally. I have passed this through to a friend. thankyou

  2. Tohid | September 19, 2011 at 1:05 pm | Permalink

    Thank you Craig for the very useful code.

    I noticed that you’ve written this post in 2008. So is there any upgrade or improved suggestion for ASP.NET 4.0 MVC 3.0 in 2011? Or it’s still the best way to use Moq against DI in MVC.

    Thx

Post a Comment

Your email is never published nor shared. Required fields are marked *

Bad Behavior has blocked 713 access attempts in the last 7 days.

Close