【问题标题】:Mock HttpContext using moq for unit test [duplicate]使用 moq 模拟 HttpContext 进行单元测试 [重复]
【发布时间】:2014-03-24 08:29:11
【问题描述】:

我需要一个 HttpContext 模拟来进行单元测试。但我正在为此苦苦挣扎。

我正在制作一种方法,可以通过 SessionIdManager 以编程方式更改 sessionId。 而 SessionIdManager 需要 HttpContext 而不是 HttpContextBase。

但我找不到任何示例来模拟 HttpContext。所有的例子都只是为了制作 HttpContextBase。

我在下面尝试过,但它们没有用

HttpContext httpContext = Mock<HttpContext>();
HttpContext httpContext = (HttpContext)GetMockHttpContextBase();

public HttpContextBase GetMockHttpContextBase()
{
   var context = new Mock<HttpContextBase>();
   var request = new Mock<HttpRequestBase>();
   var response = new Mock<HttpResponseBase>();
   var session = new Mock<HttpSessionStateBase>();
   var application = new Mock<HttpApplication>();
   var httpContext = new Mock<HttpContext>();
   var server = new Mock<HttpServerUtilityBase>();
   var user = new Mock<IPrincipal>();
   var identity = new Mock<IIdentity>();
   var urlHelper = new Mock<UrlHelper>();
   var routes = new RouteCollection();
   var requestContext = new Mock<RequestContext>();

   requestContext.Setup(x => x.HttpContext).Returns(context.Object);
   context.Setup(ctx => ctx.Request).Returns(request.Object);
   context.Setup(ctx => ctx.Response).Returns(response.Object);
   context.Setup(ctx => ctx.Session).Returns(session.Object);
   application.Setup(x => x.Context).Returns(httpContext.Object);
   context.Setup(ctx => ctx.ApplicationInstance).Returns(application.Object);
   context.Setup(ctx => ctx.Server).Returns(server.Object);
   context.Setup(ctx => ctx.User).Returns(user.Object);
   user.Setup(ctx => ctx.Identity).Returns(identity.Object);
   identity.Setup(id => id.IsAuthenticated).Returns(true);
   identity.Setup(id => id.Name).Returns("test");
   request.Setup(req => req.Url).Returns(new Uri("http://tempuri.org"));
   request.Setup(req => req.RequestContext).Returns(requestContext.Object);
   requestContext.Setup(x => x.RouteData).Returns(new RouteData());
   request.SetupGet(req => req.Headers).Returns(new NameValueCollection());

   return context.Object;
}

有什么方法可以模拟 HttpContext 或者使用 HttpContextBase 来实现 HttpContext?

请任何人帮助我。

【问题讨论】:

  • 但是就像我说的,你的链接都是关于 HttpContextBase,而不是 HttpContext。我需要'new SessionIDManager().GetSessionID(HttpContext)'的httpContext。还是谢谢。
  • 我之前试过你的第三个链接,你可以在我的示例代码中看到。但它不起作用,因为 new Mock() 抛出运行时异常,即使没有它 HttpContextBase.ApplicationInstance.Context 也会返回 null。所以它没有用。我正在使用 vs 2010,所以第四个链接也帮不了我。不过感谢您的帮助。

标签: c# asp.net-mvc-3 unit-testing mocking moq


【解决方案1】:

这是一个常见问题,问题的根源是不要模拟您不拥有的类型。与其使用复杂的模拟来尝试重现您未编写的类的行为(这意味着您正在猜测它的作用以及您需要模拟什么),不如在您的代码和外部对象 HttpContext 和模拟之间引入一个抽象那个抽象。正如模拟对象的先驱之一所说:

对我来说,关键是乔·沃尔恩斯提出了激进的概念 “不要模拟你不拥有的类型”。这意味着:停止跳跃 箍与封闭世界的图书馆合作,使用测试来发现 您的对象以及它们之间的对话。

http://higherorderlogic.com/2004/02/the-big-idea-is-messaging/

【讨论】:

  • 好建议,我可能需要一种不同的方法来处理这个问题。非常感谢迈克。
  • @percebus 已修复。
【解决方案2】:

如果您打算尝试模拟 HttpContext,那么您将不得不使用相当多的样板来从本质上模拟它。

Phil Haack 在这篇博文中详细描述了这种方法:http://haacked.com/archive/2005/06/11/simulating_httpcontext.aspx/

正如我之前所说,我想要一种“轻量级”的方法来测试这种方法。如果 HttpContext.Current 是 HttpContext 的有效实例,则不会有问题。幸运的是,HttpContext 的静态 Current 属性既可读又可写。只需将该属性设置为正确创建的 HttpContext 实例。但是,创建该实例并不像我的第一次尝试那么简单。我会省去你无聊的细节,只是告诉你我最终得到了什么。

他在这里提供了一个模拟器框架:http://haacked.com/archive/2007/06/19/unit-tests-web-code-without-a-web-server-using-httpsimulator.aspx/

请记住,您可能会冒险进行所有这些的集成测试,因为模拟这些对象所涉及的逻辑非常重要,并且可能会影响测试的可靠性。

【讨论】:

  • 尽管我选择了 Mike 的回复作为答案,但这更接近我的预期。非常详细的答案,谢谢 Lilshieste。
猜你喜欢
  • 2023-03-29
  • 2022-10-13
  • 2013-06-13
  • 2013-07-08
  • 1970-01-01
  • 1970-01-01
  • 2019-02-09
  • 2011-12-24
相关资源
最近更新 更多