how to add session to mock httpcontext?
As per scott hanselman's mock example http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx I tried to mock httpcontext using MockHelpers as code snippet below
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"]);
I noticed that the session wasn't added and didn't receive any error either. The session obje开发者_如何学Pythonct's properties had below value
Count = 0, CodePage = 0, Content = null, IsCookieLess = null, IsNewSession = null, IsReadOnly = null, IsSynchronized = null, Keys = null, LCID = 0, Mode = off, SessionId = null, Static Objects = null, SynRoot = null, TimeOut = 0
I was getting same result for Rhino mock and Moq.
Please advice me how to add session to mock httpcontext.
Thanks in advance.
Here's what I use to mock not only the session, but most other objects that you will need (request, response, etc), this code is a collection of code of Steve Sanderson and others as well as my own, note that the session is faked using a dictionary
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; }
}
}
}
}
The code you referenced explains how you can fake out the httpcontext - it doesn't actually do anything when you call "hb.Session.Add" - it just stops the test from failing because of a dependency on the HttpContext.
You can use the MVC Contrib library provided by the Outercurve Foundation to mock session state and other objects that are available during the handling of a normal request (HttpRequest, HttpResponse...etc.).
http://mvccontrib.codeplex.com/ (or use NuGet to download it)
It contains a TestHelper library which helps you to quickly create unit tests.
For example:
[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);
}
Using the TestControllerBuilder type provided by the MVC Contrib TestHelper library you can quickly initialize your controller and initialize its internal data members (HttpContext, HttpSession, TempData...).
Of course, the HttpSessionState itself is also mocked this way, so adding something to it (Session.Add) won't actually do something. As is intended, we mocked it.
Seems like you want to mock the HttpContext, but still have it setup with a working session state. Sounds like you want to do something as described here:
http://jasonbock.net/jb/Default.aspx?blog=entry.161daabc728842aca6f329d87c81cfcb
This is what i usually do
//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);
I've written a small aricle about this at
http://www.gigawebsolution.com/Posts/Details/66/Mock-Session-in-MVC3-using-Rhino-Mock
Hope this helps
A little bit late, but this is what is use.
I''m using the MoQ framework from https://code.google.com/p/moq/
Now the session is usable in the controller implementation.
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;
....
}
精彩评论