asp.net-mvc 如何在 ASP.Net MVC 中模拟控制器上的请求?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/970198/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to mock the Request on Controller in ASP.Net MVC?
提问by Nissan
I have a controller in C# using the ASP.Net MVC framework
我有一个使用 ASP.Net MVC 框架的 C# 控制器
public class HomeController:Controller{
public ActionResult Index()
{
if (Request.IsAjaxRequest())
{
//do some ajaxy stuff
}
return View("Index");
}
}
I got some tips on mocking and was hoping to test the code with the following and RhinoMocks
我得到了一些关于模拟的技巧,并希望使用以下和 RhinoMocks 测试代码
var mocks = new MockRepository();
var mockedhttpContext = mocks.DynamicMock<HttpContextBase>();
var mockedHttpRequest = mocks.DynamicMock<HttpRequestBase>();
SetupResult.For(mockedhttpContext.Request).Return(mockedHttpRequest);
var controller = new HomeController();
controller.ControllerContext = new ControllerContext(mockedhttpContext, new RouteData(), controller);
var result = controller.Index() as ViewResult;
Assert.AreEqual("About", result.ViewName);
However I keep getting this error:
但是我不断收到此错误:
Exception System.ArgumentNullException: System.ArgumentNullException : Value cannot be null. Parameter name: request at System.Web.Mvc.AjaxRequestExtensions.IsAjaxRequest(HttpRequestBase request)
异常 System.ArgumentNullException:System.ArgumentNullException:值不能为空。参数名称:在 System.Web.Mvc.AjaxRequestExtensions.IsAjaxRequest(HttpRequestBase request) 处请求
Since the Requestobject on the controller has no setter. I tried to get this test working properly by using recommended code from an answer below.
由于Request控制器上的对象没有设置器。我试图通过使用以下答案中的推荐代码来使此测试正常工作。
This used Moq instead of RhinoMocks, and in using Moq I use the following for the same test:
这使用了 Moq 而不是 RhinoMocks,在使用 Moq 时,我使用以下内容进行相同的测试:
var request = new Mock<HttpRequestBase>();
// Not working - IsAjaxRequest() is static extension method and cannot be mocked
// request.Setup(x => x.IsAjaxRequest()).Returns(true /* or false */);
// use this
request.SetupGet(x => x.Headers["X-Requested-With"]).Returns("XMLHttpRequest");
var context = new Mock<HttpContextBase>();
context.SetupGet(x => x.Request).Returns(request.Object);
var controller = new HomeController(Repository, LoginInfoProvider);
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
var result = controller.Index() as ViewResult;
Assert.AreEqual("About", result.ViewName);
but get the following error:
但得到以下错误:
Exception System.ArgumentException: System.ArgumentException : Invalid setup on a non-overridable member: x => x.Headers["X-Requested-With"] at Moq.Mock.ThrowIfCantOverride(Expression setup, MethodInfo methodInfo)
异常 System.ArgumentException:System.ArgumentException:不可覆盖成员的无效设置:x => x.Headers["X-Requested-With"] at Moq.Mock.ThrowIfCantOverride(Expression setup, MethodInfo methodInfo)
Again, it seems like I cannot set the request header. How do I set this value, in RhinoMocks or Moq?
同样,我似乎无法设置请求标头。如何在 RhinoMocks 或 Moq 中设置此值?
回答by eu-ge-ne
Using Moq:
使用最小起订量:
var request = new Mock<HttpRequestBase>();
// Not working - IsAjaxRequest() is static extension method and cannot be mocked
// request.Setup(x => x.IsAjaxRequest()).Returns(true /* or false */);
// use this
request.SetupGet(x => x.Headers).Returns(
new System.Net.WebHeaderCollection {
{"X-Requested-With", "XMLHttpRequest"}
});
var context = new Mock<HttpContextBase>();
context.SetupGet(x => x.Request).Returns(request.Object);
var controller = new YourController();
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
UPDATED:
更新:
Mock Request.Headers["X-Requested-With"]or Request["X-Requested-With"]instead of Request.IsAjaxRequest().
模拟Request.Headers["X-Requested-With"]或Request["X-Requested-With"]代替Request.IsAjaxRequest().
回答by sjmarsh
For anyone using NSubstitute I was able to modify the above answers and do something like this... (where Details is the Action method name on the controller)
对于使用 NSubstitute 的任何人,我都可以修改上述答案并执行以下操作...(其中 Details 是控制器上的 Action 方法名称)
var fakeRequest = Substitute.For<HttpRequestBase>();
var fakeContext = Substitute.For<HttpContextBase>();
fakeRequest.Headers.Returns(new WebHeaderCollection { {"X-Requested-With", "XMLHttpRequest"}});
fakeContext.Request.Returns(fakeRequest);
controller.ControllerContext = new ControllerContext(fakeContext, new RouteData(), controller);
var model = new EntityTypeMaintenanceModel();
var result = controller.Details(model) as PartialViewResult;
Assert.IsNotNull(result);
Assert.AreEqual("EntityType", result.ViewName);
回答by Phil Hale
Here is a working solution using RhinoMocks. I've based it on a Moq solution I found at http://thegrayzone.co.uk/blog/2010/03/mocking-request-isajaxrequest/
这是使用 RhinoMocks 的工作解决方案。我基于我在http://thegrayzone.co.uk/blog/2010/03/mocking-request-isajaxrequest/ 上找到的 Moq 解决方案
public static void MakeAjaxRequest(this Controller controller)
{
MockRepository mocks = new MockRepository();
// Create mocks
var mockedhttpContext = mocks.DynamicMock<HttpContextBase>();
var mockedHttpRequest = mocks.DynamicMock<HttpRequestBase>();
// Set headers to pretend it's an Ajax request
SetupResult.For(mockedHttpRequest.Headers)
.Return(new WebHeaderCollection() {
{"X-Requested-With", "XMLHttpRequest"}
});
// Tell the mocked context to return the mocked request
SetupResult.For(mockedhttpContext.Request).Return(mockedHttpRequest);
mocks.ReplayAll();
// Set controllerContext
controller.ControllerContext = new ControllerContext(mockedhttpContext, new RouteData(), controller);
}
回答by Jeroen Bernsen
Is AjaxRequest is an extension method. So you can do it the following way using Rhino:
AjaxRequest 是一个扩展方法。因此,您可以使用 Rhino 以以下方式进行操作:
protected HttpContextBase BuildHttpContextStub(bool isAjaxRequest)
{
var httpRequestBase = MockRepository.GenerateStub<HttpRequestBase>();
if (isAjaxRequest)
{
httpRequestBase.Stub(r => r["X-Requested-With"]).Return("XMLHttpRequest");
}
var httpContextBase = MockRepository.GenerateStub<HttpContextBase>();
httpContextBase.Stub(c => c.Request).Return(httpRequestBase);
return httpContextBase;
}
// Build controller
....
controller.ControllerContext = new ControllerContext(BuildHttpContextStub(true), new RouteData(), controller);
回答by Dr.Sai
Looks like you are looking for this,
看起来你正在寻找这个,
var requestMock = new Mock<HttpRequestBase>();
requestMock.SetupGet(rq => rq["Age"]).Returns("2001");
Usage in Controller :
在控制器中的用法:
public ActionResult Index()
{
var age = Request["Age"]; //This will return 2001
}
回答by Micha? Chaniewski
You need to mock HttpContextBase and put it into your ControllerContext property, like that:
您需要模拟 HttpContextBase 并将其放入您的 ControllerContext 属性中,如下所示:
controller.ControllerContext =
new ControllerContext(mockedHttpContext, new RouteData(), controller);
回答by Sharad Rastogi
To make IsAjaxRequest()to return false during Unit test you need to setup Request Headers as well as request collection value both in your test method as given below:
要IsAjaxRequest()在单元测试期间返回 false,您需要在测试方法中设置请求标头以及请求集合值,如下所示:
_request.SetupGet(x => x.Headers).Returns(new System.Net.WebHeaderCollection { { "X-Requested-With", "NotAjaxRequest" } });
_request.SetupGet(x=>x["X-Requested-With"]).Returns("NotAjaxRequest");
The reason for setting up both is hidden in implementation of IsAjaxRequest() which is given below:
设置两者的原因隐藏在 IsAjaxRequest() 的实现中,如下所示:
public static bool IsAjaxRequest(this HttpRequestBase request)<br/>
{
if (request == null)
{
throw new ArgumentNullException("request");
}
return ((request["X-Requested-With"] == "XMLHttpRequest") || ((request.Headers != null) && (request.Headers["X-Requested-With"] == "XMLHttpRequest")));
}
It uses both request Collection and header this is why we need to create setup for both Header and Request Collection.
它同时使用请求集合和头,这就是为什么我们需要为头和请求集合创建设置。
this will make the request to return false when it is not a ajax request. to make it return true you can do the following:
这将使请求在不是 ajax 请求时返回 false。要使其返回 true,您可以执行以下操作:
_httpContext.SetupGet(x => x.Request["X-Requested-With"]).Returns("XMLHttpRequest");
回答by Niraj Trivedi
I found other way to add a HttpRequestMessage object into your request during Web API as follow
我找到了其他方法在 Web API 期间将 HttpRequestMessage 对象添加到您的请求中,如下所示
[Test]
public void TestMethod()
{
var controllerContext = new HttpControllerContext();
var request = new HttpRequestMessage();
request.Headers.Add("TestHeader", "TestHeader");
controllerContext.Request = request;
_controller.ControllerContext = controllerContext;
var result = _controller.YourAPIMethod();
//Your assertion
}

