Skip to content

Instantly share code, notes, and snippets.

@ptsurbeleu
Forked from johnnyreilly/DemoAreaRegistration.cs
Last active December 14, 2015 18:09
Show Gist options
  • Save ptsurbeleu/5127531 to your computer and use it in GitHub Desktop.
Save ptsurbeleu/5127531 to your computer and use it in GitHub Desktop.
This is a forked version of John Reilly's gist that has been specifically tailored to bring testability for one of the Controller.Url.RouteUrl overloads. See below some code as an example of how this could done. P.S. Some features has been cut off from the original gist.
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
namespace DemoApp.Controllers
{
public class HomeController : System.Web.Mvc.Controller
{
//....
public ActionResult About()
{
ViewBag.Message = "Your app description page.";
return View();
}
public ActionResult RedirectMe()
{
// This is the overload of Url.RouteUrl that we want to be able to use as-is at the test time as well
var redirectUrl = this.Url.RouteUrl("Default", new { Action = "About" }, this.Request.Url.Scheme);
return this.Redirect(redirectUrl);
}
//....
}
}
using System.Collections.Generic;
using System.Linq;
using System.Web.Mvc;
using System.Web.Routing;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;
using DemoApp.Controllers;
namespace UnitTest.Controllers
{
[TestClass]
public class HomeControllerTests
{
[TestMethod]
public void WillRedirectToAboutAction()
{
// Arrange
var controller = TestableHomeController.Create("http://localhost/");
// Act
var result = controller.RedirectMe() as RedirectResult;
// Assert
Assert.IsNotNull(result);
Assert.AreEqual("http://localhost/Home/About", result.Url, "Redirect url does not match");
}
}
public class TestableHomeController : HomeController
{
private TestableHomeController(string url)
: base()
{
this.SetupRoutes();
this.SetupHttpContextMock();
// Adjust mocked request object to match our test assertions,
// eq. Assert.AreEqual("http://localhost/Home/About", result.Url)
Mock.Get(this.Request).Setup(r => r.Url).Returns(new Uri(url, UriKind.Absolute));
}
private void SetupRoutes()
{
RouteTable.Routes.Clear();
// RouteConfig has been created along with the default MVC 4 Internet App template
// So, just using it as is to re-use the application's code as much as possible
RouteConfig.RegisterRoutes(RouteTable.Routes);
}
public static TestableHomeController Create(string url = null)
{
return new TestableHomeController(url);
}
}
}
using Moq;
using System;
using System.Collections.Specialized;
using System.Web;
using System.Web.Mvc;
using System.Web.Routing;
namespace UnitTest.TestUtilities
{
/// <summary>
/// This class of MVC Mock helpers is originally based on Scott Hanselman's 2008 post:
/// http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx
/// This has been updated and tweaked to work with MVC 3 / 4 projects
/// </summary>
public static class MvcMockHelpers
{
private static HttpContextBase CreateHttpContextMock()
{
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>();
request.Setup(r => r.AppRelativeCurrentExecutionFilePath).Returns("/");
request.Setup(r => r.ApplicationPath).Returns("/");
response.Setup(s => s.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(s => s);
response.SetupProperty(res => res.StatusCode, (int)System.Net.HttpStatusCode.OK);
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);
return context.Object;
}
public static void SetupHttpContextMock(this Controller controller, RouteData routeData = null, RouteCollection routes = null)
{
var httpContext = CreateHttpContextMock();
// If values not passed then initialise
routeData = routeData ?? new RouteData();
routes = routes ?? RouteTable.Routes;
var requestContext = new RequestContext(httpContext, routeData);
var context = new ControllerContext(requestContext, controller);
// Modify the controller
controller.Url = new UrlHelper(requestContext, routes);
controller.ControllerContext = context;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment