我在现有应用程序中有一个SessionManager类,如下所示:
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");
}
当我对Landing方法运行单元测试时,测试失败,因为HttpContext.Current为null。我在单元测试中模拟了Session对象,如果我尝试直接在Landing方法中访问Session(即Session [“SomeValue”]),它可以工作,但任何依赖于SessionManager的代码都会被破坏。
底线是我想要一个类,我可以使用它以通用的强类型方式访问Session值,但也可以进行单元测试。任何人都有关于如何修改此代码以实现此目的的任何建议?
答案 0 :(得分:1)
如果您已经在测试的HttpContextBase中模拟了Session,那么您需要做的就是更改SessionManager
以接受您的自定义HttpContextBase(例如,在[ThreadStatic]
字段中)
或者,将SessionManager
类本身设为非static
,并使HttpContextBase
作为构造函数参数。
一般情况下,永远不要使用HttpContext.Current
。如果您希望您的代码可以测试或可重用。
答案 1 :(得分:0)
您只能通过引入另一个抽象层来使其可测试。这是你自己的IOurHttpContext和OurDotNetHttpContext:用于真实app的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; }
}
很容易。但它可能很复杂。
答案 2 :(得分:0)
您可以将HttpContext.Current设置为_httpContext