I have a SessionManager class in an existing application that looks like this:
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);
}
}
}
In my HomeController, I have code like the following:
public ActionResult Landing(string id)
{
SessionManager.GetItem<Campaign>(SessionKeys.Campaign)
// commented for brevity
return View("Index");
}
When I run a unit test on the Landing method, the test fails because HttpContext.Current is null. I've mocked the Session object in my unit tests, and if I attempt to access Session directly in the Landing method (i.e. Session["SomeValue"]) it works, but any code that relies on the SessionManager is broken.
Bottom line is that I want a class I can use to access Session values in a generic, strongly typed manner, but that can also be unit tested. Anyone have any suggestions on how I can modify this code to achieve that?
If you've already mocked the Session in your test's HttpContextBase, all you need to do is change SessionManager
to accept your custom HttpContextBase (eg, in a [ThreadStatic]
field)
Alternatively, make the SessionManager
class itself non-static
, and make it take an HttpContextBase
as a constructor parameter.
In general, you should never use HttpContext.Current
. if you want your code to be testable or reusable.