【问题标题】:how to unit test for session variable in controller in mvc如何在 mvc 的控制器中对会话变量进行单元测试
【发布时间】:2012-09-14 11:11:52
【问题描述】:
我正在对我的控制器进行单元测试。
在我的一种控制器方法中,我正在设置会话变量:
public void Index()
{ Session["foo"] = "bar";
return View();
}
如何进行单元测试?问题是测试时 Session 属性为空。无法注入,因为 Session 属性是只读的。
我不想使用任何第三方工具或模拟。
【问题讨论】:
标签:
asp.net-mvc
unit-testing
session-variables
httpcontext
【解决方案2】:
无法注入,因为 Session 属性是只读的。
这意味着你不能使用 setter 注入,但你可以使用构造函数注入,即为你的控制器添加一个构造函数,类似于:
MyController(Session session)
{
m_session = session;
// then call your main constructor
}
Session getSession()
{
return m_session;
}
然后您可以在测试期间使用这个单独的构造函数。
【解决方案3】:
我同意@rouen。不要直接使用 Session["foo"]。但我认为拥有 ValueProvider ans 可能不是一个实际的解决方案,因为我们只存储很少的变量,而这些值可能是并且很可能不是您的完整模型。
所以我的方法类似于 Vic Smith 建议的方法,但对 IOC(和 Mock)更友好。
我会创建一个提供者(即服务)来检索会话变量
public class SessionVariableProvider : ISessionVariableProvider
{
public object GetSessionValue(string key)
{
if (!HttpContext.Current.Session.IsNewSession
&& HttpContext.Current.Session[key] != null)
{
return HttpContext.Current.Session[key];
}
throw new ArgumentNullException(key);
}
public void SetSessionValue(string key, object value)
{
HttpContext.Current.Session[key] = value;
}
}
public interface ISessionVariableProvider
{
object GetSessionValue(string key);
void SetSessionValue(string key, object value);
}
修改你的控制器期望 ISessionVariableProvider 作为参数。
public class TestController: Controller
{
protected readonly ISessionVariableProvider _sessionVariableProvider;
protected InowiaControllerBase(ISessionVariableProvider sessionVariableProvider)
{
Guard.ArgumentNotNull(sessionVariableProvider, "sessionVariableProvider");
this._sessionVariableProvider = sessionVariableProvider;
}
public ActionResult Index()
{
_sessionVariableProvider.SetSessionValue("foo", "bar");
var foo2 = (string)_sessionVariableProvider.GetSessionValue("foo2");
return View();
}
}
在测试时创建您自己的 ISessionVariableProvider 测试实现并将其传递给控制器。