2010-08-17 54 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的邏輯是什麼?如果我沒有記錯,它應該正確地選擇協議和端口,以及任何虛擬目錄,站點等。