I've followed this answer to mock HttpContext, Request, Response and User and set Controller.ControllerContext and Controller.Url.
Controller.Url is most definitely not null before calling controller.Index(). However, inside controller.Index(), it is null. It seems very strange. What am I missing?
Here's my test fixture:
[TestFixture]
public class ControllerFixtureBase
{
private Mock<HttpContextBase> _httpContextMock;
private RouteCollection _routes;
[SetUp]
public void SetUp()
{
var requestMock = new Mock<HttpRequestBase>();
requestMock.SetupGet(x => x.ApplicationPath)
.Returns("/");
requestMock.SetupGet(x => x.Url)
.Returns(new Uri("http://localhost/a", UriKind.Absolute));
requestMock.SetupGet(x => x.ServerVariables)
.Returns(new NameValueCollection());
var responseMock = new Mock<HttpResponseBase>();
responseMock.Setup(x => x.ApplyAppPathModifier(It.IsAny<string>()))
.Returns((string url) => url);
var principalMock = new Mock<IPrincipal>();
principalMock.SetupGet(p => p.Identity)
.Returns(new GenericIdentity("testuser"));
principalMock.Setup(p => p.IsInRole(ApplicationRoles.DataAdmin))
.Returns(false);
_httpContextMock = new Mock<HttpContextBase>();
_httpContextMock.Setup(x => x.User)
.Returns(principalMock.Object);
_httpContextMock.Setup(x => x.Request)
.Returns(requestMock.Object);
_httpContextMock.SetupGet(x => x.Response)
.Returns(responseMock.Object);
_routes = new RouteCollection();
MvcApplication.RegisterRoutes(_routes);
}
protected void PrepareController(Controller controller)
{
var requestContext = new RequestContext(_httpContextMock.Object, new RouteData());
controller.ControllerContext = new ControllerContext(requestContext, controller);
controller.Url = new UrlHelper(requestContext, _routes);
}
[Test]
public void Index()
{
HomeController controller = new HomeController();
PrepareController(controller);
Assert.That(controller.Url, Is.Not.Null);
Assert.That(controller.ViewBag, Is.Not.Null);
ViewResult viewResult = controller.Index() as ViewResult;
Assert.That(viewResult, Is.Not.Null);
Assert.That(viewResult.ViewBag.IndexUrl, Is.EqualTo("/"));
}
}
And here's my very simple action:
[Authorize]
public class HomeController : Controller
{
public ActionResult Index()
{
ViewBag.Message = "Modify this template to jump-start your ASP.NET MVC application.";
// System.NullReferenceException : Object reference not set to an instance of an object.
ViewBag.IndexUrl = Url.Action("Index");
return View();
}
}