NSubstitute返回空字符串

问题描述

我正在测试以下方法

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

我正在测试如下:

public void test()
{
    var userIpAddressHelper = Substitute.For<IUserIpAddressHelper>();
    userIpAddressHelper.GetUserIpAddress(Arg.Any<HttpContext>()).Returns("0.0.0.2");
  
    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"]);
}

但是,由于userIpAddress 的值为""为空字符串而不是我设置的0.0.0.2,因此测试失败。谁能指出我在哪里出问题了?

解决方法

userIpAddress肯定是""吗?看来您原始测试中的Returns已正确指定,但是如果IUserIpAddressHelper是接口,则其替代品将不会存有IsIpAddressOddOrEven的结果,因此它将始终返回false,即使GetUserIpAddress被存根以返回"0.0.0.2"

要使测试反映生产代码如何通过数据,您可以将两个成员都存根:

var userIpAddressHelper = Substitute.For<IUserIpAddressHelper>();
userIpAddressHelper.GetUserIpAddress(Arg.Any<HttpContext>()).Returns("0.0.0.2");
userIpAddressHelper.IsIpAddressOddOrEven("0.0.0.2").Returns(true);

这将测试生产代码是否正确地将GetUserIpAddress的结果传递到IsIpAddressOddOrEven

注意:我们也可以将其存根与"ip-address-result"一起使用,并且仍然可以使用。我们不需要返回有效的奇/偶结果,因为我们没有使用IUserIpAddressHelper的真实实现,而只是测试的替代品。如果您发现有必要在许多测试中替换IUserIpAddressHelper,并且希望它像真实的实现一样工作(即,它实际上将返回地址是奇数还是偶数),则编写{ {1}}。

另一种避免在TestUserIpAddressHelperGetUserIpAddress的结果之间具有依赖性的方法是将接口更改为具有结合了两种操作的IsIpAddressOddOrEven方法。这样,您只需要存根一个即可进行测试。

,

如果您对System.Web.HttpContext.Current有疑问,可以尝试模拟IsIpAddressOddOrEven方法。他们将为您的测试做相同的工作。 像这样:

public void Test()
{
    var userIpAddressHelper = Substitute.For<IUserIpAddressHelper>();
    userIpAddressHelper.IsIpAddressOddOrEven(Arg.Any<string>()).Returns(true);
  
    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"]);
}