【问题标题】:MVC Mock HttpContextBase which is used in a helperMVC Mock HttpContextBase 用于帮助程序
【发布时间】:2011-03-31 00:04:21
【问题描述】:

我在我的控制器和我在互联网上某个地方找到的视图中使用了一个助手。助手在我的控制器“Url.SiteRoot();”中被这样调用 每当调用助手时,如何让我的控制器不抛出异常?我正在使用 MVCContrib 和 moq 进行单元测试。

我正在考虑在助手中实现某种检查,但感觉 MVCContrib 框架或 moq 应该能够处理这个问题,因此我不需要在助手中添加异常代码就可以了通过单元测试。

您可以在此处查看 Helper 代码:-

namespace System.Web.Mvc {
public static class UrlHelpers {

    public static string SiteRoot(HttpContextBase context) {
        return SiteRoot(context, true);
    }

    public static string SiteRoot(HttpContextBase context, bool usePort) {
        var Port = context.Request.ServerVariables["SERVER_PORT"];
        if (usePort) {
            if (Port == null || Port == "80" || Port == "443")
                Port = "";
            else
                Port = ":" + Port;
        }
        var Protocol = context.Request.ServerVariables["SERVER_PORT_SECURE"];
        if (Protocol == null || Protocol == "0")
            Protocol = "http://";
        else
            Protocol = "https://";

        var appPath = context.Request.ApplicationPath;
        if (appPath == "/")
            appPath = "";

        var sOut = Protocol + context.Request.ServerVariables["SERVER_NAME"] + Port + appPath;
        return sOut;

    }

    public static string SiteRoot(this UrlHelper url) {
        return SiteRoot(url.RequestContext.HttpContext);
    }


    public static string SiteRoot(this ViewPage pg) {
        return SiteRoot(pg.ViewContext.HttpContext);
    }

    public static string SiteRoot(this ViewUserControl pg) {
        var vpage = pg.Page as ViewPage;
        return SiteRoot(vpage.ViewContext.HttpContext);
    }

    public static string SiteRoot(this ViewMasterPage pg) {
        return SiteRoot(pg.ViewContext.HttpContext);
    }

    public static string GetReturnUrl(HttpContextBase context) {
        var returnUrl = "";

        if (context.Request.QueryString["ReturnUrl"] != null) {
            returnUrl = context.Request.QueryString["ReturnUrl"];
        }

        return returnUrl;
    }

    public static string GetReturnUrl(this UrlHelper helper) {
        return GetReturnUrl(helper.RequestContext.HttpContext);
    }

    public static string GetReturnUrl(this ViewPage pg) {
        return GetReturnUrl(pg.ViewContext.HttpContext);
    }

    public static string GetReturnUrl(this ViewMasterPage pg) {
        return GetReturnUrl(pg.Page as ViewPage);
    }

    public static string GetReturnUrl(this ViewUserControl pg) {
        return GetReturnUrl(pg.Page as ViewPage);
    }
}
}

【问题讨论】:

    标签: c# asp.net-mvc asp.net-mvc-2 moq mvccontrib


    【解决方案1】:

    正如@Jeremy Frey 所写,您会遇到异常,因为您未能存根/伪造 HttpContext 的某些重要部分。

    如何使用:

    Request.Url.GetLeftPart(System.UriPartial.Authority) 
    

    而不是尝试自己构建构建 url 的逻辑?如果我没记错的话,它应该会正确选择协议和端口,以及任何虚拟目录、站点等。

    【讨论】:

      【解决方案2】:

      您可能已经意识到,您从扩展方法中获取异常的原因是由于模拟对象上未实现的属性或方法,例如HttpContextBase 上的请求,或 UrlHelper 上的 RequestContext。

      查看here 发布的一些策略,了解如何模拟扩展方法调用。我个人更喜欢this strategy,它会让你重构你的扩展方法以保证在运行时可交换。

      例如,而不是:

      public static class UrlHelperExtensions 
      {
          public static string GetReturnUrl(this UrlHelper helper) 
          {
              return // your implementation of GetReturnUrl here
          }
      
      }
      

      你会有:

      public interface IUrlHelperExtensions 
      {
          string GetReturnUrl(UrlHelper helper);
      }
      
      public static class UrlHelperExtensions
      {
          public static IUrlHelperExtensions Extensions(this UrlHelper target)
          {
              return UrlHelperExtensionFactory(target);
          }
      
          static UrlExtensions 
          {
              UrlHelperExtensionFactory = () => new DefaultUrlHelperExtensionStrategy();
          }
      
          public static Func UrlHelperExtensionFactory { get; set; }
      }   
      
      public DefaultUrlHelperExtensionStrategy : IUrlHelperExtensions 
      {
          public string GetReturnUrl(UrlHelper helper) 
          {
              return // your implementation of GetReturnUrl here
          }
      }
      

      您需要将调用扩展方法的方式从 urlHelper.GetReturnUrl() 更改为 urlHelper.Extensions().GetReturnUrl(),并且在单元测试期间,您可以将 UrlHelperExtensions.UrlHelperExtensionFactory 设置为模拟对象,但是这样,您可以在测试时控制扩展方法的行为。

      【讨论】:

        【解决方案3】:

        该代码看起来有点复杂。我认为这做同样的事情,并且会更容易测试。 (但我不确定为什么需要这样做。)

        public string FullApplicationPath(HttpRequestBase request)
        {
            var path = request.Url.AbsoluteUri.Replace(request.Url.AbsolutePath,string.Empty);
            if (!string.IsNullOrEmpty(request.Url.Query))
            {
                path = path.Replace(request.Url.Query, string.Empty);
            }
            return path + request.ApplicationPath;
        }
        

        【讨论】:

          猜你喜欢
          • 2014-06-04
          • 1970-01-01
          • 2014-12-06
          • 1970-01-01
          • 2010-09-07
          • 1970-01-01
          • 2012-04-11
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多