根据scott hanselman的模拟示例http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx我尝试使用MockHelpers模拟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,Static Objects = null,SynRoot = null,TimeOut = 0
我得到了Rhino mock和Moq的相同结果。
请建议我如何将会话添加到模拟httpcontext。
提前致谢。
答案 0 :(得分:3)
这是我用来模拟会话,但你需要的大多数其他对象(请求,响应等),这段代码是史蒂夫桑德森和其他人以及我自己的代码的集合,请注意会话是使用字典伪造的
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; }
}
}
}
}
答案 1 :(得分:2)
您引用的代码解释了如何伪造httpcontext - 当您调用“hb.Session.Add”时它实际上没有做任何事情 - 它只是因为依赖于HttpContext而停止测试失败。 / p>
答案 2 :(得分:1)
您可以使用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
答案 3 :(得分:1)
这就是我通常做的事情
//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
希望这有帮助
答案 4 :(得分:0)
有点晚了,但这是有用的。
我正在使用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;
....
}