【问题标题】: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


【解决方案1】:

不要在控制器方法中使用 Session["foo"] 之类的东西。最佳实践是让操作方法不知道任何类似上下文的全局对象。你的行动方法需要的一切都应该以论证的形式提供给她。请注意,模型绑定的内置机制的工作方式与此完全相同——您不使用 Request.Form[],而是让“幕后的人”将其作为参数传递给您的操作。

现在对于会话,您可以执行相同的操作 - 为您编写非常简单的 ValueProvider,它将知道如何识别您想要从会话中填充的参数,然后您就完成了。在生产中,您的操作将与会话一起使用,在测试中,您不能简单地将任何您想要的值作为参数传递给它们。

要获得灵感,请查看http://www.prideparrot.com/blog/archive/2012/7/how_to_create_a_custom_session_value_provider

【讨论】:

    【解决方案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 测试实现并将其传递给控制器​​。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2018-02-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-08-12
        • 2016-03-18
        • 1970-01-01
        • 2014-05-27
        相关资源
        最近更新 更多