Moq and MvcMockHelpers

Posted by on in Blogs
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;

Comments are not available for public users. Please login first to view / add comments.