【问题标题】:how to add session to mock httpcontext?如何将会话添加到模拟 httpcontext?
【发布时间】:2013-10-04 15:31:20
【问题描述】:

根据 scott hanselman 的模拟示例 http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx,我尝试使用 MockHelpers 作为下面的代码 sn-p 来模拟 httpcontext

controller = GetAccountController();

ActionResult result = controller.ChangePassword();

HttpContextBase hb = MvcMockHelpers.FakeHttpContext("~/Account/ChangePassword");
hb.Session.Add("id", 5);

// Assert Assert.AreEqual(5, (int)hb.Session["id"]);

我注意到没有添加会话,也没有收到任何错误。会话对象的属性值低于

Count = 0, CodePage = 0, Content = null, IsCookieLess = null, IsNewSession = null, IsReadOnly = null, IsSynchronized = null, Keys = null, LCID = 0, Mode = off, SessionId = null, 静态对象 = null, SynRoot = null, TimeOut = 0

对于 Rhino mock 和 Moq,我得到了相同的结果。

请告诉我如何将会话添加到模拟 httpcontext。

提前致谢。

【问题讨论】:

    标签: asp.net-mvc unit-testing


    【解决方案1】:

    这不仅是我用来模拟会话的东西,而且是你需要的大多数其他对象(请求、响应等),这段代码是 Steve Sanderson 和其他人以及我自己的代码的集合,请注意会话是使用字典伪造的

    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Web;
    using System.Web.Routing;
    using System.Web.Mvc;
    
    namespace ECWeb2.UnitTests {
        public class ContextMocks {
            public Moq.Mock<HttpContextBase> HttpContext { get; private set; }
            public Moq.Mock<HttpRequestBase> Request { get; private set; }
            public Moq.Mock<HttpResponseBase> Response { get; private set; }
            public RouteData RouteData { get; private set; }
        public ContextMocks(Controller onController) {
            // Define all the common context objects, plus relationships between them
            HttpContext = new Moq.Mock<HttpContextBase>();
            Request = new Moq.Mock<HttpRequestBase>();
            Response = new Moq.Mock<HttpResponseBase>();
            HttpContext.Setup(x => x.Request).Returns(Request.Object);
            HttpContext.Setup(x => x.Response).Returns(Response.Object);
            HttpContext.Setup(x => x.Session).Returns(new FakeSessionState());
            Request.Setup(x => x.Cookies).Returns(new HttpCookieCollection());
            Response.Setup(x => x.Cookies).Returns(new HttpCookieCollection());
            Request.Setup(x => x.QueryString).Returns(new NameValueCollection());
            Request.Setup(x => x.Form).Returns(new NameValueCollection());
    
            // Apply the mock context to the supplied controller instance
            RequestContext rc = new RequestContext(HttpContext.Object, new RouteData());
            onController.ControllerContext = new ControllerContext(rc, onController);
            onController.Url = new UrlHelper(rc);
        }
    
        ContextMocks() {
        }
    
        // Use a fake HttpSessionStateBase, because it's hard to mock it with Moq
        private class FakeSessionState : HttpSessionStateBase {
            Dictionary<string, object> items = new Dictionary<string, object>();
            public override object this[string name] {
                get { return items.ContainsKey(name) ? items[name] : null; }
                set { items[name] = value; }
            }
        }
    }
    

    }

    【讨论】:

      【解决方案2】:

      您引用的代码解释了如何伪造 httpcontext - 当您调用“hb.Session.Add”时它实际上并没有做任何事情 - 由于对 HttpContext 的依赖,它只是阻止测试失败。

      【讨论】:

        【解决方案3】:

        您可以使用 Outercurve Foundation 提供的 MVC Contrib 库来模拟会话状态和在处理正常请求(HttpRequest、HttpResponse...等)期间可用的其他对象。

        http://mvccontrib.codeplex.com/(或使用 NuGet 下载)

        它包含一个TestHelper library,它可以帮助您快速创建单元测试。

        例如:

        [TestMethod]
        public void TestSomething()
        {
            TestControllerBuilder builder = new TestControllerBuilder();
        
            // Arrange
            HomeController controller = new HomeController();
        
            builder.InitializeController(controller);
        
            // Act
            ViewResult result = controller.About() as ViewResult;
        
            // Assert
            Assert.IsNotNull(result);
        }
        

        使用 MVC Contrib TestHelper 库提供的 TestControllerBuilder 类型,您可以快速初始化控制器并初始化其内部数据成员(HttpContext、HttpSession、TempData...)。

        当然,HttpSessionState 本身也是这样模拟的,所以向它添加一些东西(Session.Add)实际上不会做任何事情。正如预期的那样,我们模拟了它。

        似乎您想模拟 HttpContext,但仍将其设置为工作会话状态。听起来您想按照此处所述进行操作:

        http://jasonbock.net/jb/Default.aspx?blog=entry.161daabc728842aca6f329d87c81cfcb

        【讨论】:

          【解决方案4】:

          这是我经常做的事情

          //Mock The Sesssion
          _session = MockRepository.GenerateStrictMock<httpsessionstatebase>();
          _session.Stub(s => s["Connectionstring"]).Return(Connectionstring);
          
          //Mock The Context 
          _context = MockRepository.GenerateStrictMock<httpcontextbase>();
          _context.Stub(c => c.Session).Return(_session);
          
          var databaseExplorerController = new DatabaseExplorerController(repository);
          
          //Assign COntext to controller
          databaseExplorerController.ControllerContext = new ControllerContext(_context, new RouteData(),
                                                                               _databaseExplorer);
          

          我已经写了一篇关于这个的小文章

          http://www.gigawebsolution.com/Posts/Details/66/Mock-Session-in-MVC3-using-Rhino-Mock

          希望对你有帮助

          【讨论】:

            【解决方案5】:

            有点晚了,但这是有用的。

            我正在使用 https://code.google.com/p/moq/ 的 MoQ 框架

            现在会话可以在控制器实现中使用。

                private class MockHttpSession : HttpSessionStateBase
                {
                    readonly Dictionary<string, object> _sessionDictionary = new Dictionary<string, object>();
                    public override object this[string name]
                    {
                        get
                        {
                            object obj = null;
                            _sessionDictionary.TryGetValue(name, out obj);
                            return obj;
                        }
                        set { _sessionDictionary[name] = value; }
                    }
                }
            
                private ControllerContext CreateMockedControllerContext()
                {
                    var session = new MockHttpSession();
                    var controllerContext = new Mock<ControllerContext>();
                    controllerContext.Setup(m => m.HttpContext.Session).Returns(session);
            
                    return controllerContext.Object;
                }
            
                [TestMethod]
                public void Index()
                {
                    // Arrange
                    MyController controller = new MyController();
                    controller.ControllerContext = CreateMockedControllerContext(); 
            
                    // Act
                    ViewResult result = controller.Index() as ViewResult;
            
                    ....
                }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-04-07
              • 2021-11-11
              • 2018-05-04
              • 1970-01-01
              • 1970-01-01
              • 2017-04-18
              • 2014-11-26
              相关资源
              最近更新 更多