C# 依赖于SessionManager类且依赖于HttpContext.Current的单元测试代码
我在一个现有应用程序中有一个SessionManager类,如下所示:C# 依赖于SessionManager类且依赖于HttpContext.Current的单元测试代码,c#,unit-testing,session,httpcontext,C#,Unit Testing,Session,Httpcontext,我在一个现有应用程序中有一个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)
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);
}
}
}
公共类SessionManagerBase
{
公共静态无效附加项(TKey,对象项)
{
_httpContext.Session[key.ToString()]=项;
}
公共静态T GetItem(TKey)
{
对象项=_httpContext.Session[key.ToString()];
returnitem==null?默认值(T):(T)Convert.ChangeType(item,typeof(T));
}
//等等。。。
私有静态HttpContextBase\u httpContext
{
得到
{
返回新的HttpContextWrapper(HttpContext.Current);
}
}
}
在我的HomeController中,我有如下代码:
public ActionResult Landing(string id)
{
SessionManager.GetItem<Campaign>(SessionKeys.Campaign)
// commented for brevity
return View("Index");
}
公共操作结果登录(字符串id)
{
SessionManager.GetItem(SessionKeys.Campaign)
//简明扼要
返回视图(“索引”);
}
当我在Landing方法上运行单元测试时,测试失败,因为HttpContext.Current为null。我在单元测试中模拟了Session对象,如果我试图在Landing方法中直接访问Session(即Session[“SomeValue”]),它会工作,但依赖SessionManager的任何代码都会被破坏
底线是我想要一个类,我可以用它以一种通用的、强类型的方式访问会话值,但它也可以进行单元测试。有人对我如何修改此代码以实现这一点有什么建议吗?如果您已经在测试的HttpContextBase中模拟了会话,那么您需要做的就是更改SessionManager以接受自定义HttpContextBase(例如,在
[ThreadStatic]
字段中)
或者,将SessionManager
类本身设置为非静态的static
,并将HttpContextBase
作为构造函数参数
通常,您不应该使用
HttpContext.Current
。如果您希望您的代码是可测试的或可重用的。您只能通过引入另一个抽象层使其可测试。这是您自己的IOurHttpContext和我们的DotNetHttpContext:IOurHttpContext(用于real app)和我们的TestHttpContext:IOuthtpContext(用于测试,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; }
}
很简单。不过它可能非常复杂。您可以将HttpContext.Current设置为您的_HttpContext