Reputation: 822
I have the following method in my HomeController. The purpose is to split users based on IP address to test different versions of the home page:
[HttpGet]
public ActionResult Index()
{
var userIpAddress = GetUserIpAddress();
if (IsIpAddressOddOrEven(userIpAddress))
{
return RedirectToAction(HomePage);
}
return RedirectToAction(HomePageAlternative);
}
The GetUserIpAddress
method:
private string GetUserIpAddress()
{
HttpContext context = System.Web.HttpContext.Current;
var ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
if (!string.IsNullOrEmpty(ipAddress))
{
string[] addresses = ipAddress.Split(',');
if (addresses.Length != 0)
{
return addresses[0];
}
}
return context.Request.ServerVariables["REMOTE_ADDR"];
}
I want to write a unit test to ensure that this works properly. However, every time the unit test runs it is just taking the IP address I currently have. I am struggling to work out how to mock the result of the 'GetUserIpAddress' method to return an odd or even string. My attempt so far:
[Test]
public void Test()
{
var controller = CreateMvcController<HomeController>();
var result = controller.Index();
controller.HttpContext.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].Returns("1");
Assert.IsInstanceOf<RedirectToRouteResult>(result);
var redirectToRouteResult = result as RedirectToRouteResult;
Assert.AreEqual(HomeController.HomePage, redirectToRouteResult.RouteValues["action"]);
}
I got the error that the result of controller.HttpContext.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].Returns("1");
is not a string but a HttpResponseBase, and in any case I am not convinced I am going about this the right way. Please can someone point me in the right direction to do this? Thank you
Upvotes: 3
Views: 1213
Reputation: 834
I suggest you to move GetUserIpAddress
method to a helper class which you can inject into HomeController
. Therefore you can mock it while doing the unit tests.
Your HomeController
will be like this
public HomeController(IUserIpAddressHelper userIpAddressHelper)
{
_userIpAddressHelper = userIpAddressHelper;
}
[HttpGet]
public ActionResult Index()
{
var userIpAddress = _userIpAddressHelper.GetUserIpAddress(System.Web.HttpContext.Current);
if (_userIpAddressHelper.IsIpAddressOddOrEven(userIpAddress))
{
return RedirectToAction(HomePage);
}
return RedirectToAction(HomePageAlternative);
}
So, you'll be able to mock UserIpAddressHelper
and inject it when writing the test.
public void Test()
{
var userIpAddressHelper = Substitute.For<IUserIpAddressHelper>();
userIpAddressHelper.GetUserIpAddress(Arg.Any<HttpContext>()).Returns("0.0.0.0");
var controller = new HomeController(userIpAddressHelper);
var result = controller.Index();
Assert.IsInstanceOf<RedirectToRouteResult>(result);
var redirectToRouteResult = result as RedirectToRouteResult;
Assert.AreEqual(HomeController.HomePage, redirectToRouteResult.RouteValues["action"]);
}
Upvotes: 2