NSubstitute 返回空字符串

NSubstitute returning empty string

我正在测试以下方法:

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,因此测试失败。谁能指出我这里哪里出错了?

如果您在使用 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"]);
}

userIpAddress肯定是""吗?看起来您原始测试中的 Returns 指定得很好,但是如果 IUserIpAddressHelper 是一个接口,那么它的替代项不会为 IsIpAddressOddOrEven 存根,所以它总是 return false 即使 GetUserIpAddress 存根为 return "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" 一起使用,它仍然可以工作。我们不需要有效的 odd/even 结果 returned,因为我们没有使用 IUserIpAddressHelper 的真正实现,只是测试的替代品。如果您发现有必要在很多测试中替换 IUserIpAddressHelper 并且您希望它像一个真正的实现一样(即它实际上 return 无论地址是奇数还是偶数),它可能更容易写一个 TestUserIpAddressHelper.

另一种避免 GetUserIpAddressIsIpAddressOddOrEven 的结果之间存在依赖关系的方法是将接口更改为具有结合这两种操作的 bool IsIpAddressOddOrEven(HttpContext context) 方法。这样一来,您只需要存根一个即可进行测试。