如何在mvc中对控制器中的会话变量进行单元测试

时间:2012-09-14 11:11:52

标签: asp.net-mvc unit-testing session-variables httpcontext

我正在对我的控制器进行单元测试。

在我的一个控制器方法中,我正在设置会话变量:

public void Index()
{       Session["foo"] = "bar";
        return View();
}

我如何对此进行单元测试?问题是测试时Session属性为null。无法进行注入,因为Session属性是只读的。

我不想使用任何第三方工具或嘲笑。

3 个答案:

答案 0 :(得分:5)

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

现在对于会话你也可以这样做 - 给你写一个非常简单的ValueProvider,它将知道如何识别你想从会话中填充的参数,并且你已经完成了。在生产中,您的操作将与会话一起使用,在测试中您无法将任何您想要的值作为参数传递给它们。

有关灵感,请查看此http://www.prideparrot.com/blog/archive/2012/7/how_to_create_a_custom_session_value_provider

答案 1 :(得分:1)

  

因为Session属性是只读的,所以无法进行注入。

这意味着你不能使用setter注入,但是你可以使用构造函数注入,即为你的控制器添加一个类似的构造函数:

MyController(Session session)
{
    m_session = session;

    // then call your main constructor
}

Session getSession()
{
    return m_session;
}

然后,您可以在测试期间使用此单独的构造函数。

答案 2 :(得分:0)

我同意@rouen。不要直接使用Session [“foo”]。但我认为使用ValueProvider ans可能不是一个实用的解决方案,因为我们只存储很少的变量,而这些值可能并且很可能不是完整的模型。 因此,我的方法类似于维克史密斯的建议,但更多的是IOC(和模拟)友好。

我会创建一个提供程序(即服务)来检索会话变量

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);
    }

修改您的Controller期望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测试实现并将其传递给控制器​​时。