C# 如果在测试时在System.Web.UI.Util处出现异常,如何对我的HtmlHelper扩展方法进行单元测试?

C# 如果在测试时在System.Web.UI.Util处出现异常,如何对我的HtmlHelper扩展方法进行单元测试?,c#,asp.net-mvc-3,unit-testing,moq,html-helper,C#,Asp.net Mvc 3,Unit Testing,Moq,Html Helper,嗯。。。问题更复杂,问题的标题说。首先,我有一个HtmlHelper的扩展方法,它根据当前的路由参数生成带有参数的html链接。也就是说,如果我在../page?param1=val1¶m2=val2,当我调用我的方法ActionQuryLink生成链接,例如@Html.ActionQuryLink(“link text”,“action”,new{param3=“value3”})时,我将获得一个到的链接。扩展类本身是: public static class ActionLinkHe

嗯。。。问题更复杂,问题的标题说。首先,我有一个HtmlHelper的扩展方法,它根据当前的路由参数生成带有参数的html链接。也就是说,如果我在
../page?param1=val1¶m2=val2
,当我调用我的方法
ActionQuryLink
生成链接,例如
@Html.ActionQuryLink(“link text”,“action”,new{param3=“value3”})
时,我将获得一个到
的链接。扩展类本身是:

public static class ActionLinkHelper
    {
        public static MvcHtmlString ActionQueryLink(this HtmlHelper htmlHelper, string linkText, string action)
        {
            return (ActionQueryLink(htmlHelper, linkText, action, null, null));
        }
        public static MvcHtmlString ActionQueryLink(this HtmlHelper htmlHelper, string linkText, string action, object routeValues)
        {

            /*line 16*/return (ActionQueryLink(htmlHelper, linkText, action, routeValues, null));
        }

        public static MvcHtmlString ActionQueryLink(this HtmlHelper htmlHelper, string linkText, string action, object routeValues, IDictionary<string, object> htmlAttributes)
        {
            var queryString = htmlHelper.ViewContext.HttpContext.Request.QueryString;

            var newRoute = routeValues == null
                ? htmlHelper.ViewContext.RouteData.Values
                : new RouteValueDictionary(routeValues);

            foreach(string key in queryString.Keys)
            {
                if(!newRoute.ContainsKey(key))
                    newRoute.Add(key, queryString[key]);
            }
            /*line 32*/string generatedLink = HtmlHelper.GenerateLink(
                htmlHelper.ViewContext.RequestContext,
                htmlHelper.RouteCollection,
                linkText,
                null,
                action,
                null,
                newRoute,
                htmlAttributes);

            return new MvcHtmlString(generatedLink);
        }
    }
和堆栈跟踪:

at System.Web.UI.Util.GetUrlWithApplicationPath(HttpContextBase context, String url)
   at System.Web.Routing.RouteCollection.NormalizeVirtualPath(RequestContext requestContext, String virtualPath)
   at System.Web.Routing.RouteCollection.GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
   at System.Web.Mvc.RouteCollectionExtensions.GetVirtualPathForArea(RouteCollection routes, RequestContext requestContext, String name, RouteValueDictionary values, ref Boolean usingAreas)
   at System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues)
   at System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues)
   at System.Web.Mvc.HtmlHelper.GenerateLinkInternal(RequestContext requestContext, RouteCollection routeCollection, String linkText, String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, IDictionary`2 htmlAttributes, Boolean includeImplicitMvcValues)
   at System.Web.Mvc.HtmlHelper.GenerateLink(RequestContext requestContext, RouteCollection routeCollection, String linkText, String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, IDictionary`2 htmlAttributes)
   at System.Web.Mvc.HtmlHelper.GenerateLink(RequestContext requestContext, RouteCollection routeCollection, String linkText, String routeName, String actionName, String controllerName, RouteValueDictionary routeValues, IDictionary`2 htmlAttributes)
   at Core.Helpers.ActionLinkHelper.ActionQueryLink(HtmlHelper htmlHelper, String linkText, String action, Object routeValues, IDictionary`2 htmlAttributes) in ActionLinkHelper.cs: line 32
   at Core.Helpers.ActionLinkHelper.ActionQueryLink(HtmlHelper htmlHelper, String linkText, String action, Object routeValues) in ActionLinkHelper.cs: line 16
   at TestSite.UnitTests.Helpers.ActionLinkHeplerTests.ActionLinkHeplerShouldGenerateCorrectActionLink() in ActionLinkHeplerTests.cs: line 51
嗯,我真的很抱歉收到这么多代码。
但我正在研究这个问题大约3天。正如您所看到的,即使不是在某些MVC库中,也会在
System.Web.UI.Util
中发生错误。即使我可以找到
System.Web.UI.Util
源代码,并将其作为一个项目添加到我的解决方案中,我也无法强制MVC框架使用这个项目,而不是使用global assembly cash中的
System.Web.UI.Util
。老实说,在我的解决方案中,将MVC从GAC替换为MVC的sources项目甚至是非常困难的,因为它非常复杂,有很多依赖项,当我尝试这样做时,我遇到了很多错误,其中大多数是外部库,它们已经使用了来自global assembly cash的MVC assembly。最重要的是,我的helper方法在我的项目中运行良好,它只在测试时调用异常。所以我的建议是,助手的测试条件不完整,或者可能是错误的。总之,我的问题是如何使用Moq模拟html帮助程序扩展方法的正确条件,或者,可能还有其他问题吗?

结果表明,要测试依赖路由信息的帮助程序,需要模拟
RequestContext.HttpContext的以下方法:

  • RequestContext.HttpContext.Request.ApplicationPath
    -应返回类似于根路径的内容(即
    @“/”
  • RequestContext.HttpContext.Response.ApplyAppPathModifier
    -只需返回其输入参数:
样本:

request.Setup(r => r.ApplicationPath).Returns(@"/");
response.Setup(r => r.ApplyAppPathModifier(It.IsAny<string>()))
                .Returns((string s) => s);
request.Setup(r=>r.ApplicationPath)。返回(@/);
response.Setup(r=>r.ApplyAppPathModifier(It.IsAny()))
.返回((字符串s)=>s);

您提供了堆栈跟踪,是否也可以提供异常?当然,对不起。我已经编辑了这个问题。仍然让你感到厌烦,但是你能在你的代码中添加一条注释来显示ActionLinkHelper中的第16行和第32行(以及ActionLinkHelperTets中的第51行)在哪里吗?谢谢你,Alex!它帮助了我:)这就像一种魅力。这应该是可以接受的答案。
at System.Web.UI.Util.GetUrlWithApplicationPath(HttpContextBase context, String url)
   at System.Web.Routing.RouteCollection.NormalizeVirtualPath(RequestContext requestContext, String virtualPath)
   at System.Web.Routing.RouteCollection.GetVirtualPath(RequestContext requestContext, RouteValueDictionary values)
   at System.Web.Mvc.RouteCollectionExtensions.GetVirtualPathForArea(RouteCollection routes, RequestContext requestContext, String name, RouteValueDictionary values, ref Boolean usingAreas)
   at System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues)
   at System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues)
   at System.Web.Mvc.HtmlHelper.GenerateLinkInternal(RequestContext requestContext, RouteCollection routeCollection, String linkText, String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, IDictionary`2 htmlAttributes, Boolean includeImplicitMvcValues)
   at System.Web.Mvc.HtmlHelper.GenerateLink(RequestContext requestContext, RouteCollection routeCollection, String linkText, String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, IDictionary`2 htmlAttributes)
   at System.Web.Mvc.HtmlHelper.GenerateLink(RequestContext requestContext, RouteCollection routeCollection, String linkText, String routeName, String actionName, String controllerName, RouteValueDictionary routeValues, IDictionary`2 htmlAttributes)
   at Core.Helpers.ActionLinkHelper.ActionQueryLink(HtmlHelper htmlHelper, String linkText, String action, Object routeValues, IDictionary`2 htmlAttributes) in ActionLinkHelper.cs: line 32
   at Core.Helpers.ActionLinkHelper.ActionQueryLink(HtmlHelper htmlHelper, String linkText, String action, Object routeValues) in ActionLinkHelper.cs: line 16
   at TestSite.UnitTests.Helpers.ActionLinkHeplerTests.ActionLinkHeplerShouldGenerateCorrectActionLink() in ActionLinkHeplerTests.cs: line 51
request.Setup(r => r.ApplicationPath).Returns(@"/");
response.Setup(r => r.ApplyAppPathModifier(It.IsAny<string>()))
                .Returns((string s) => s);