Asp.net mvc 如何将会话添加到模拟httpcontext?

Asp.net mvc 如何将会话添加到模拟httpcontext?,asp.net-mvc,unit-testing,Asp.net Mvc,Unit Testing,根据scott hanselman的模拟示例,我尝试使用模拟助手模拟httpcontext,代码片段如下 controller = GetAccountController(); ActionResult result = controller.ChangePassword(); HttpContextBase hb = MvcMockHelpers.FakeHttpContext("~/Account/ChangePassword"); hb.Session.Add("id", 5);

根据scott hanselman的模拟示例,我尝试使用模拟助手模拟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,iscookeless=null,IsNewSession=null,IsReadOnly=null,IsSynchronized=null,Keys=null,LCID=0,Mode=off,SessionId=null,Static Objects=null,SynRoot=null,TimeOut=0

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

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


提前感谢。

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

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

以下是我用来模拟的内容,不仅是会话,还有您需要的大多数其他对象(请求、响应等),此代码是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; }
        }
    }
}
使用System.Collections.Generic;
使用System.Collections.Specialized;
使用System.Web;
使用System.Web.Routing;
使用System.Web.Mvc;
命名空间ECWeb2.UnitTests{
公共类contextmock{
public Moq.Mock HttpContext{get;private set;}
公共Moq.Mock请求{get;private set;}
公共Moq.Mock响应{get;private set;}
公共路由数据路由数据{get;私有集;}
公共上下文模拟(控制器onController){
//定义所有公共上下文对象,以及它们之间的关系
HttpContext=new Moq.Mock();
请求=新的Moq.Mock();
响应=新Moq.Mock();
Setup(x=>x.Request).Returns(Request.Object);
Setup(x=>x.Response).Returns(Response.Object);
Setup(x=>x.Session).Returns(new FakeSessionState());
Request.Setup(x=>x.Cookies).Returns(新的HttpCookieCollection());
Response.Setup(x=>x.Cookies).Returns(新的HttpCookieCollection());
Setup(x=>x.QueryString).Returns(newnamevalueCollection());
Setup(x=>x.Form).Returns(newNameValueCollection());
//将模拟上下文应用于提供的控制器实例
RequestContext rc=newrequestcontext(HttpContext.Object,newroutedata());
onController.ControllerContext=新的ControllerContext(rc,onController);
Url=newurlHelper(rc);
}
ContextMocks(){
}
//使用一个假的HttpSessionStateBase,因为很难用Moq来模拟它
私有类FakeSessionState:HttpSessionStateBase{
字典项=新字典();
公共重写对象[字符串名称]{
获取{return items.ContainsKey(name)→items[name]:null;}
设置{items[name]=value;}
}
}
}

}以下是我用来模拟会话的内容,以及您需要的大多数其他对象(请求、响应等),这些代码是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; }
        }
    }
}
使用System.Collections.Generic;
使用System.Collections.Specialized;
使用System.Web;
使用System.Web.Routing;
使用System.Web.Mvc;
命名空间ECWeb2.UnitTests{
公共类contextmock{
public Moq.Mock HttpContext{get;private set;}
公共Moq.Mock请求{get;private set;}
公共Moq.Mock响应{get;private set;}
公共路由数据路由数据{get;私有集;}
公共上下文模拟(控制器onController){
//定义所有公共上下文对象,以及它们之间的关系
HttpContext=new Moq.Mock();
请求=新的Moq.Mock();
响应=新Moq.Mock();
Setup(x=>x.Request).Returns(Request.Object);
Setup(x=>x.Response).Returns(Response.Object);
Setup(x=>x.Session).Returns(new FakeSessionState());
Request.Setup(x=>x.Cookies).Returns(新的HttpCookieCollection());
Response.Setup(x=>x.Cookies).Returns(新的HttpCookieCollection());
Setup(x=>x.QueryString).Returns(newnamevalueCollection());
Setup(x=>x.Form).Returns(newNameValueCollection());
//将模拟上下文应用于提供的控制器实例
RequestContext rc=newrequestcontext(HttpContext.Object,newroutedata());
onController.ControllerContext=新的ControllerContext(rc,onController);
Url=newurlHelper(rc);
}
ContextMocks(){
}
//使用一个假的HttpSessionStateBase,因为很难用Moq来模拟它
私有类FakeSessionState:HttpSessionStateBase{
字典项=新字典();
公共重写对象[字符串名称]{
获取{return items.ContainsKey(name)→items[name]:null;}
设置{items[name]=value;}
}
}
}

}/P>< P>您可以使用OutTrror基金会提供的MVC控件库来模拟处理正常请求时可用的其他会话状态和其他对象(HypReQuest,HttpResponse等)。

(或使用NuGet下载)

它包含帮助您快速创建单元测试的

例如:

[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本身也是模拟的
    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;

        ....
    }