¿Cómo se burla de la Solicitud de Controlador en ASP.Net MVC?

Tengo un controlador en C # usando el marco ASP.Net MVC

public class HomeController:Controller{ public ActionResult Index() { if (Request.IsAjaxRequest()) { //do some ajaxy stuff } return View("Index"); } } 

Recibí algunos consejos sobre burlas y esperaba probar el código con lo siguiente y RhinoMocks

 var mocks = new MockRepository(); var mockedhttpContext = mocks.DynamicMock(); var mockedHttpRequest = mocks.DynamicMock(); 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); 

Sin embargo sigo recibiendo este error:

Exception System.ArgumentNullException: System.ArgumentNullException: el valor no puede ser nulo. Nombre del parámetro: solicitud en System.Web.Mvc.AjaxRequestExtensions.IsAjaxRequest (solicitud HttpRequestBase)

Dado que el objeto Request en el controlador no tiene setter. Traté de que esta prueba funcionara correctamente utilizando el código recomendado de la respuesta a continuación.

Esto usó Moq en lugar de RhinoMocks, y al usar Moq uso lo siguiente para la misma prueba:

 var request = new Mock(); // 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(); 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); 

pero recibe el siguiente error:

Exception System.ArgumentException: System.ArgumentException: configuración no válida en un miembro no invalidable: x => x.Headers [“X-Requested-With”] en Moq.Mock.ThrowIfCantOverride (Configuración de expresión, MethodInfo methodInfo)

Nuevamente, parece que no puedo configurar el encabezado de la solicitud. ¿Cómo configuro este valor en RhinoMocks o Moq?

Usando Moq :

 var request = new Mock(); // 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(); context.SetupGet(x => x.Request).Returns(request.Object); var controller = new YourController(); controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller); 

ACTUALIZADO:

Mock Request.Headers["X-Requested-With"] o Request["X-Requested-With"] lugar de Request.IsAjaxRequest() .

Aquí hay una solución de trabajo que usa RhinoMocks. Lo he basado en una solución de Moq que encontré en http://thegrayzone.co.uk/blog/2010/03/mocking-request-isajaxrequest/

 public static void MakeAjaxRequest(this Controller controller) { MockRepository mocks = new MockRepository(); // Create mocks var mockedhttpContext = mocks.DynamicMock(); var mockedHttpRequest = mocks.DynamicMock(); // 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); } 

Para cualquiera que use NSubstitute, pude modificar las respuestas anteriores y hacer algo como esto … (donde Details es el nombre del método de acción en el controlador)

  var fakeRequest = Substitute.For(); var fakeContext = Substitute.For(); 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); 

Es AjaxRequest es un método de extensión. Entonces puedes hacerlo de la siguiente manera usando Rhino:

  protected HttpContextBase BuildHttpContextStub(bool isAjaxRequest) { var httpRequestBase = MockRepository.GenerateStub(); if (isAjaxRequest) { httpRequestBase.Stub(r => r["X-Requested-With"]).Return("XMLHttpRequest"); } var httpContextBase = MockRepository.GenerateStub(); httpContextBase.Stub(c => c.Request).Return(httpRequestBase); return httpContextBase; } // Build controller .... controller.ControllerContext = new ControllerContext(BuildHttpContextStub(true), new RouteData(), controller); 

Parece que estás buscando esto,

  var requestMock = new Mock(); requestMock.SetupGet(rq => rq["Age"]).Returns("2001"); 

Uso en el controlador:

  public ActionResult Index() { var age = Request["Age"]; //This will return 2001 } 

Debes burlarte de HttpContextBase y ponerlo en tu propiedad ControllerContext, así:

 controller.ControllerContext = new ControllerContext(mockedHttpContext, new RouteData(), controller); 

Para hacer que IsAjaxRequest() devuelva falso durante la prueba de unidad, necesita configurar los encabezados de solicitud y solicitar el valor de recostackción tanto en su método de prueba como a continuación:

 _request.SetupGet(x => x.Headers).Returns(new System.Net.WebHeaderCollection { { "X-Requested-With", "NotAjaxRequest" } }); _request.SetupGet(x=>x["X-Requested-With"]).Returns("NotAjaxRequest"); 

El motivo para configurar ambos está oculto en la implementación de IsAjaxRequest () que se muestra a continuación:

 public static bool IsAjaxRequest(this HttpRequestBase request)
{ if (request == null) { throw new ArgumentNullException("request"); } return ((request["X-Requested-With"] == "XMLHttpRequest") || ((request.Headers != null) && (request.Headers["X-Requested-With"] == "XMLHttpRequest"))); }

Utiliza tanto la colección de solicitudes como el encabezado. Es por eso que debemos crear la configuración tanto para el encabezado como para la colección de solicitudes.

esto hará que la solicitud devuelva falso cuando no es una solicitud AJAX. para que sea verdadero, puede hacer lo siguiente:

 _httpContext.SetupGet(x => x.Request["X-Requested-With"]).Returns("XMLHttpRequest"); 

Encontré otra manera de agregar un objeto HttpRequestMessage en su solicitud durante la API web como sigue

 [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 }