Skip to content

Instantly share code, notes, and snippets.

@rally25rs
Created January 8, 2012 15:26
Show Gist options
  • Star 13 You must be signed in to star a gist
  • Fork 5 You must be signed in to fork a gist
  • Save rally25rs/1578697 to your computer and use it in GitHub Desktop.
Save rally25rs/1578697 to your computer and use it in GitHub Desktop.
MvcMockHelpers.cs - Helper Utility for Mocking MVC3 Controllers with Moq.
using System;
using System.Collections.Specialized;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
using Moq;
/// <summary>
/// This helper class can be used to set up Moq mocks of MVC3 controllers.
/// Slightly modified from the original version from Scott Hanselman's blog:
/// http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx
/// </summary>
public static class MvcMockHelpers
{
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>();
context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session.Object);
context.Setup(ctx => ctx.Server).Returns(server.Object);
context.SetupProperty(ctx => ctx.User);
return context.Object;
}
public static HttpContextBase FakeHttpContext(string url)
{
var context = FakeHttpContext();
context.Request.SetupRequestUrl(url);
return context;
}
public static void SetFakeControllerContext(this Controller controller, string requestUrl = "~/Nowhere/")
{
var httpContext = FakeHttpContext(requestUrl);
var requestContext = new RequestContext(httpContext, new RouteData());
var context = new ControllerContext(requestContext, controller);
controller.ControllerContext = context;
controller.Url = new UrlHelper(requestContext);
}
private static string GetUrlFileName(string url)
{
return url.Contains("?") ? url.Substring(0, url.IndexOf("?")) : url;
}
private static NameValueCollection GetQueryStringParameters(string url)
{
if (url.Contains("?"))
{
var parameters = new NameValueCollection();
var parts = url.Split("?".ToCharArray());
var keys = parts[1].Split("&".ToCharArray());
foreach (var key in keys)
{
var part = key.Split("=".ToCharArray());
parameters.Add(part[0], part[1]);
}
return parameters;
}
return null;
}
public static void SetHttpMethodResult(this HttpRequestBase request, string httpMethod)
{
Mock.Get(request)
.Setup(req => req.HttpMethod)
.Returns(httpMethod);
}
public static void SetupRequestUrl(this HttpRequestBase request, string url)
{
if (url == null)
throw new ArgumentNullException("url");
if (!url.StartsWith("~/"))
throw new ArgumentException("Sorry, we expect a virtual url starting with \"~/\".");
var mock = Mock.Get(request);
mock.Setup(req => req.QueryString)
.Returns(GetQueryStringParameters(url));
mock.Setup(req => req.AppRelativeCurrentExecutionFilePath)
.Returns(GetUrlFileName(url));
mock.Setup(req => req.PathInfo)
.Returns(string.Empty);
mock.SetupGet(x => x.Url).Returns(new Uri(url.Replace("~/", "http://www.nowhere.com/")));
}
}
@rally25rs
Copy link
Author

Sample Usage:

var controller = new SomeController();
controller.SetFakeControllerContext("~/Somewhere/");

This will set up the HttpContext, RequestContext, and UrlHelper inside the controller, so that the controller code can still execute.

@rally25rs
Copy link
Author

Also allows the user Principal to be set on the HttpContext:

var controller = new SomeController();
controller.SetFakeControllerContext();
controller.HttpContext.User = new GenericPrincipal(new GenericIdentity("username"), new string[0]);

@branflake2267
Copy link

I'm new at this... How do I integrate this into the Controller? Are you adding that static method to the controller?

@kikoanis
Copy link

Added a modified version of this that creates/returns a dictionary of all mocked objects in a controller
Gist can be found here
https://gist.github.com/3955791

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment