From the standard LogOn method in the account controller in MVC3 applications, how can I test the
Url.IsLocalUrl(returnUrl.ToString())
line of code where the url is not local? In other words, what url do I have to feed into this line of code when unit testing, to get it to return false?
I have used the following thinking this would be returned as false(non local):
Uri uri = new Uri(@"http://www.google.com/blahblah.html");
But it just threw a null exception in the unit tests
Edit: I should add that the LogOn method now looks like this:
public ActionResult LogOn(LogOnModel model, System.Uri returnUrl)
if (ModelState.IsValid) {
bool loggedOn = LogOn(model);
if (loggedOn) {
if (Url.IsLocalUrl(returnUrl.ToString())) {
return Redirect(returnUrl.ToString());
}
else {
return RedirectToAction("Index", "Home");
}
}
else {
ModelState.AddModelError("", "The user name or password provided is incorrect.");
}
}
// If we got this far, something failed, redisplay form
return View(viewModel);
}
Some style cop/code analysis errors forced a changed from a string parameter to System.uri parameter but it is very similar to the standard original.
Just to clarify, in a unit test – I want to test and assert the outcome of hitting the Else line where it redirects to Home/Index, so I need to pass something to into the (System.Uri)returnUrl that will make it return false on Url.IsLocalUrl and not throw an exception
Further Edit:
I am using MvcContrib testhelper, which is pretty good at mocking a lot of the httpcontext and web stuff:
Builder = new TestControllerBuilder();
UserController = new UserController();
Builder.InitializeController(UserController);
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:
Remark: since you have actually shown the
LogOnimplementation 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 theif (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:
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: