使用NSubstitute模拟MVC单元测试中的用户IP地址

时间:2020-08-20 10:26:53

标签: c# asp.net-mvc nsubstitute

我的HomeController中具有以下方法。目的是根据IP地址拆分用户以测试首页的不同版本:

        [HttpGet]
        public ActionResult Index()
        {
            var userIpAddress = GetUserIpAddress();

            if (IsIpAddressOddOrEven(userIpAddress))
            {
                return RedirectToAction(HomePage);
            }

            return RedirectToAction(HomePageAlternative);
        }

GetUserIpAddress方法:

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"];
        }

我想编写一个单元测试以确保其正常工作。但是,每次单元测试运行时,它只会占用我当前拥有的IP地址。我正在努力研究如何模拟“ GetUserIpAddress”方法的结果以返回奇数或偶数字符串。到目前为止,我的尝试:

        [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"]);
        }

我得到一个错误,即 controller.HttpContext.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].Returns("1");的结果不是字符串,而是HttpResponseBase,无论如何我都不相信我会采用正确的方法。请有人能指出我正确的方向吗?谢谢

1 个答案:

答案 0 :(得分:2)

我建议您将GetUserIpAddress方法移到可以插入HomeController的帮助程序类中。因此,您可以在进行单元测试时模拟它。

您的HomeController会是这样

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);
}

因此,您可以模拟UserIpAddressHelper并在编写测试时将其注入。

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"]);
}
相关问题