2012-09-14 78 views
0

我在現有的應用程序,它看起來像這樣有一個SessionManager類單元測試代碼:與依賴依靠SessionManager類上HttpContext.Current

public class SessionManagerBase<TKey> 
{ 
    public static void AddItem(TKey key, object item) 
    { 
     _httpContext.Session[key.ToString()] = item; 
    } 

    public static T GetItem<T>(TKey key) 
    { 
     object item = _httpContext.Session[key.ToString()]; 
     return item == null ? default(T) : (T) Convert.ChangeType(item, typeof (T)); 
    } 

    // etc... 

    private static HttpContextBase _httpContext 
    { 
     get 
     { 
      return new HttpContextWrapper(HttpContext.Current); 
     } 
    } 
} 

在我的HomeController中,我有一個像下面的代碼:

public ActionResult Landing(string id) 
{ 
    SessionManager.GetItem<Campaign>(SessionKeys.Campaign) 

    // commented for brevity 

    return View("Index"); 
} 

當運行在降落方法的單元測試,測試失敗,因爲HttpContext.Current爲空。我在單元測試中嘲笑了Session對象,並且如果我試圖直接在Landing方法(即Session [「SomeValue」])中訪問Session,它將起作用,但任何依賴於SessionManager的代碼都會被破壞。

底線是,我想我可以用一個類來訪問會話值的泛型,強類型的方式,但也可以單元測試。任何人有任何建議,我可以如何修改此代碼來實現?

回答

1

如果你已經嘲笑會議在測試的HttpContextBase,所有你需要做的是改變SessionManager接受您的自定義HttpContextBase(例如,在[ThreadStatic]場)

或者,使SessionManager類本身不 - static,並使其作爲構造函數參數使用HttpContextBase

一般來說,你不應該使用HttpContext.Current。如果你想要你的代碼是可測試的或可重用的。

0

您只能通過引入另一個抽象層來使其可測試。這是你自己的IOurHttpContext和OurDotNetHttpContext:IOurHttpContext爲真正的應用程序和OurTestHttpContext:IOutHttpContext進行測試(後者不需要與moq)。 OurDotNetHttpContext可能如下所示:

public interface IOutHttpContext { 
    object GetSessionVar(string key); 
    void SetSessionVar(string key, object value); 
} 
public class OurDotNetHttpContext : IOutHttpContext { 
    public object GetSessionVar(string key) { return HttpContext.Current.Session[key]; } 
    public void SetSessionVar(string key, object value) { HttpContext.Current.Session[key] = value; } 
} 

很容易。儘管如此,它可能會很複雜。

0

你可以設置HttpContext.Current到你的_httpContext