如何在HtmlHelper上测试需要模拟RouteData.Values的扩展方法

时间:2019-04-25 09:20:53

标签: c# unit-testing asp.net-core moq asp.net-core-2.2

我正在尝试为.NET core 2.2 MVC Web应用程序中使用的以下扩展方法编写一些单元测试:

public static string IsSelected(this IHtmlHelper htmlHelper, string controllers, string actions = null, string cssClass = "active")
{
    string currentAction = htmlHelper.ViewContext.RouteData.Values["action"] as string;
    string currentController = htmlHelper.ViewContext.RouteData.Values["controller"] as string;

    IEnumerable<string> acceptedActions = (actions ?? currentAction).Split(',');
    IEnumerable<string> acceptedControllers = (controllers ?? currentController).Split(',');

    if(actions != null)
    {
        return acceptedActions.Contains(currentAction) && acceptedControllers.Contains(currentController) ? cssClass : String.Empty;
    }

    return acceptedControllers.Contains(currentController) ? cssClass : String.Empty;
}

如您所见,它将检查当前RouteData.Values["action"]RouteData.Values["controller"]ViewContext的值,并在匹配时返回给定的字符串。

到目前为止,我的单元测试看起来像这样:

public void TestIsSelected()
{
    var htmlHelperMock = new Mock<IHtmlHelper>();

    htmlHelperMock.Setup(m => m.ViewContext.RouteData.Values["action"]).Returns("Index");
    htmlHelperMock.Setup(m => m.ViewContext.RouteData.Values["controller"]).Returns("Home");

    var actualPass = Extensions.IsSelected(htmlHelperMock.Object, "Home");
    var actualFail = Extensions.IsSelected(htmlHelperMock.Object, "Test");

    Assert.AreEqual("active", actualPass);
    Assert.AreEqual(string.Empty, actualFail);
}

但是,似乎无法以这种方式设置RouteData.Values[]值,因为在运行测试时会生成以下错误消息:

Message: Test method ExtensionsTests.TestIsSelected threw exception: 
System.NotSupportedException: Invalid setup on a non-virtual (overridable in VB) member: m => m.Values["action"]

我在Moq方面的经验有限,因此可能会错误地设置模拟吗?也许还有另一种方法可以设置这些值,以便测试能够正确运行?我真的很感谢有关如何实现这一目标的任何建议。

0 个答案:

没有答案