Unit testing Url.IsLocalUrl(returnUrl.ToString()), how can I get it to return false in unit test?
You need to mock the HttpContext as well as the UrlHelper instance on the controller that you are unit testing. Here's an example of how that unit test might look like if you are using Moq:
[TestMethod]
public void LogOn_Should_Redirect_To_Home_If_Authentication_Succeeds_But_Not_Local_ReturnUrl_Is_Provided()
{
// arrange
var sut = new AccountController();
var model = new LogOnModel();
var returnUrl = new Uri("http://www.google.com");
var httpContext = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
httpContext.Setup(x => x.Request).Returns(request.Object);
request.Setup(x => x.Url).Returns(new Uri("http://localhost:123"));
var requestContext = new RequestContext(httpContext.Object, new RouteData());
sut.Url = new UrlHelper(requestContext);
// act
var actual = sut.LogOn(model, returnUrl);
// assert
Assert.IsInstanceOfType(actual, typeof(RedirectToRouteResult));
var result = (RedirectToRouteResult)actual;
Assert.AreEqual("Home", result.RouteValues["controller"]);
Assert.AreEqual("Index", result.RouteValues["action"]);
}
Remark: since you have actually shown the LogOn
implementation that you are calling to verify the credentials, you might need to adapt the unit test to ensure that this method returns true in the first place given the model in order to enter the if (loggedOn)
clause.
UPDATE:
It seems that you are using MvcContrib.TestHelper which does all the HttpContext mocking setup for you. So all that you need to do is to mock the relevant parts for your unit test:
[TestMethod]
public void LogOn_Should_Redirect_To_Home_If_Authentication_Succeeds_But_Not_Local_ReturnUrl_Is_Provided()
{
// arrange
var sut = new AccountController();
new TestControllerBuilder().InitializeController(sut);
var model = new LogOnModel();
var returnUrl = new Uri("http://www.google.com");
sut.HttpContext.Request.Expect(x => x.Url).Return(new Uri("http://localhost:123"));
// act
var actual = sut.LogOn(model, returnUrl);
// assert
actual
.AssertActionRedirect()
.ToController("Home")
.ToAction("Index");
}
Normally the first 2 lines of the unit test could be moved to the global [SetUp]
method to avoid repeating them in each unit test for this controller so that now your test becomes a bit cleaner:
[TestMethod]
public void LogOn_Should_Redirect_To_Home_If_Authentication_Succeeds_But_Not_Local_ReturnUrl_Is_Provided()
{
// arrange
var model = new LogOnModel();
var returnUrl = new Uri("http://www.google.com");
_sut.HttpContext.Request.Expect(x => x.Url).Return(new Uri("http://localhost:123"));
// act
var actual = _sut.LogOn(model, returnUrl);
// assert
actual
.AssertActionRedirect()
.ToController("Home")
.ToAction("Index");
}