2010-08-17 69 views
1

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

我想在助手中实现某种检查,但它感觉像MVCContrib框架或moq应该能够处理这个,所以我不需要添加异常代码在我的助手只是为了能够通过单元测试。

你可以在这里看到助手代码: -

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

回答

0

你可能已经意识到,你得到您的扩展方法例外的原因是由于在嘲笑的对象,例如,未实现属性或方法请求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设置为模拟对象,但这样,您可以在测试时控制扩展方法的行为。

0

该代码看起来有点复杂。我认为这是做同样的事情,并会更容易测试。 (我不知道为什么它需要虽然是。)

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

由于@Jeremy弗雷写你得到的异常,因为你不能存根/假的HttpContext的一些关键部分。

如何使用:

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

,而不是试图建立自己构建的URL的逻辑是什么?如果我没有记错,它应该正确地选择协议和端口,以及任何虚拟目录,站点等。