如何使用 Moq 在 ASP.NET MVC 中模拟 HttpContext?
Posted
技术标签:
【中文标题】如何使用 Moq 在 ASP.NET MVC 中模拟 HttpContext?【英文标题】:How do I mock the HttpContext in ASP.NET MVC using Moq? 【发布时间】:2010-11-29 23:02:20 【问题描述】:[TestMethod]
public void Home_Message_Display_Unknown_User_when_coockie_does_not_exist()
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
context
.Setup(c => c.Request)
.Returns(request.Object);
HomeController controller = new HomeController();
controller.HttpContext = context; //Here I am getting an error (read only).
...
我的基本控制器覆盖了获取此 requestContext 的 Initialize。我试图传递这个,但我没有做正确的事情。
protected override void Initialize(System.Web.Routing.RequestContext requestContext)
base.Initialize(requestContext);
我在哪里可以获得有关使用 Moq 模拟我的 RequestContext 和 HttpContext 的更多信息?我正在尝试模拟 cookie 和一般上下文。
【问题讨论】:
【参考方案1】:HttpContext是只读的,但实际上是从ControllerContext派生的,可以设置。
controller.ControllerContext = new ControllerContext( context.Object, new RouteData(), controller );
【讨论】:
这个对我有用,它允许我在控制器上设置一个模拟 HttpContext。【参考方案2】:创建请求、响应并将它们都放到 HttpContext 中:
HttpRequest httpRequest = new HttpRequest("", "http://mySomething/", "");
StringWriter stringWriter = new StringWriter();
HttpResponse httpResponse = new HttpResponse(stringWriter);
HttpContext httpContextMock = new HttpContext(httpRequest, httpResponse);
【讨论】:
问题是关于 *Base 类,即 HttpRequestBase,而不是 HttpRequest - 不知道为什么我自己都需要它们,更烦人的是它们被“密封”。无法设置 LogonUserIdentity :( 如果他们编组了我的参考,仍然可以通过远程处理,所以这应该不是问题。 @ChrisKimpton:作为最后的手段,总是有反思 ;-) 这在将它附加到控制器时有效,如下所示:controller.ControllerContext = new ControllerContext( new HttpContextWrapper(httpContextMock), new RouteData(), controller); 是的。你确实可以设置 .LogonUserIdentity -- _request.Setup(n => n.LogonUserIdentity).Returns((WindowsIdentity.GetCurrent));【参考方案3】:感谢用户 0100110010101。
它对我有用,在这里我在为以下代码编写测试用例时遇到了问题:
var currentUrl = Request.Url.AbsoluteUri;
这是解决问题的行
HomeController controller = new HomeController();
//Mock Request.Url.AbsoluteUri
HttpRequest httpRequest = new HttpRequest("", "http://mySomething", "");
StringWriter stringWriter = new StringWriter();
HttpResponse httpResponse = new HttpResponse(stringWriter);
HttpContext httpContextMock = new HttpContext(httpRequest, httpResponse);
controller.ControllerContext = new ControllerContext(new HttpContextWrapper(httpContextMock), new RouteData(), controller);
可能对其他人有帮助。
【讨论】:
我似乎无法使用 HttpRequest 类型 - 现在还有别的吗? 这没什么用,因为 HttpRequest 中的所有字段都是不可变的【参考方案4】:以下是我使用 ControllerContext 传递虚假应用程序路径的方法:
[TestClass]
public class ClassTest
private Mock<ControllerContext> mockControllerContext;
private HomeController sut;
[TestInitialize]
public void TestInitialize()
mockControllerContext = new Mock<ControllerContext>();
sut = new HomeController();
[TestCleanup]
public void TestCleanup()
sut.Dispose();
mockControllerContext = null;
[TestMethod]
public void Index_Should_Return_Default_View()
// Expectations
mockControllerContext.SetupGet(x => x.HttpContext.Request.ApplicationPath)
.Returns("/foo.com");
sut.ControllerContext = mockControllerContext.Object;
// Act
var failure = sut.Index();
// Assert
Assert.IsInstanceOfType(failure, typeof(ViewResult), "Index() did not return expected ViewResult.");
【讨论】:
为什么需要传递虚假的应用程序路径? MVC 代码将执行它,如果它不存在则抛出空异常。【参考方案5】:以下是如何设置的示例:Mocking HttpContext HttpRequest and HttpResponse for UnitTests (using Moq)
注意真正有助于简化这个模拟类的使用的扩展方法:
var mockHttpContext = new API_Moq_HttpContext();
var httpContext = mockHttpContext.httpContext();
httpContext.request_Write("<html><body>".line());
httpContext.request_Write(" this is a web page".line());
httpContext.request_Write("</body></html>");
return httpContext.request_Read();
以下是如何使用 moq 编写单元测试以检查 HttpModule 是否按预期工作的示例:Unit Test for HttpModule using Moq to wrap HttpRequest
更新:此 API 已重构为
HttpContextFactory.cs 这多个 Http* Extension Methods 文件【讨论】:
链接已损坏 - 请在您的答案中包含代码【参考方案6】:var httpResponse = new HttpResponseMessage(HttpStatusCode.OK);
httpResponse.Content = new StringContent("Your response text");
【讨论】:
以上是关于如何使用 Moq 在 ASP.NET MVC 中模拟 HttpContext?的主要内容,如果未能解决你的问题,请参考以下文章
UrlHelper 类在 Asp.net mvc 中引发空异常