2009-06-09 7 views
146

que tienen un controlador en C# utilizando el marco de ASP.Net MVC¿Cómo se burla de la solicitud de controlador en ASP.Net MVC?

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

me dieron algunos consejos sobre burlas y tenía la esperanza de probar el código con el siguiente y 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); 

Sin embargo sigo conseguir este error:

Exception System.ArgumentNullException: System.ArgumentNullException : Value cannot be null. Parameter name: request at System.Web.Mvc.AjaxRequestExtensions.IsAjaxRequest(HttpRequestBase request)

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

este Usado Moq en lugar de RhinoMocks, y en el uso Moq utilizo el siguiente para la misma prueba:

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); 

pero consigo el error siguiente:

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)

Una vez más, parece como si no se puede establecer el encabezado de la solicitud. ¿Cómo configuro este valor en RhinoMocks o Moq?

+0

Reemplazar Request.IsAjaxRequest con Request.IsAjaxRequest() –

+0

Mock Request.Headers ["X-Requested-With"] o Request ["X-Requested-With"] en lugar de Request.IsAjaxRequest(). He actualizado mi pregunta –

+0

[prueba esto] (http://stackoverflow.com/questions/1228179/mocking-httpcontextbase-with-moq) – danfromisrael

Respuesta

190

Uso 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); 

Actualizado:

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

+1

Aparece el mensaje "El argumento de tipo para el método 'ISetupGetter Moq.Mock . SetupGet .... no se puede deducir de uage. Intente especificar explícitamente los argumentos de tipo ? ¿Qué tipo puedo configurar 'var request =' a pesar de que para conseguir que esto funcione – Nissan

+0

acaba de actualizar mi respuesta - no Request.IsAjaxRequest pero Request.IsAjaxRequest() Modificar una pregunta demasiado –

+0

todavía genera: Excepción \t sistema. .ArgumentException: System.ArgumentException: configuración no válida en un miembro no invalidable: \t x => x.IsAjaxRequest() \t en Moq.Mock.ThrowIfCantOverride (Configuración de expresión, MethodInfo methodInfo) – Nissan

3

Necesitas burlarse HttpContextBase y ponerlo en su propiedad ControllerContext, así:

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

Aquí se puede ver cómo se burlan de la colección de formularios, el escenario será similar: Mocking the HttpRequest in ASP.NET MVC

+0

y ¿qué se burló de HttpContext necesita burlarse? El objeto RequestContext que necesita necesita un objeto HttpContextBase() en el constructor, y HttpContextBase() no tiene ningún constructor que acepte cero parámetros. – Nissan

+0

Solo use un marco de burla, no intente construir esos objetos directamente ... –

+0

Intenté: var mocks = new MockRepository(); var mockedhttpContext = mocks.DynamicMock (); var mockedHttpRequest = mocks.DynamicMock (); SetupResult.For (mockedhttpContext.Request) .Return (mockedHttpRequest); var controller = new HomeController (Repository, LoginInfoProvider); controller.ControllerContext = new mockedhttpContext, new RouteData(), controlador); var result = controller.Index() como ViewResult; Sin embargo, sigue recibiendo la misma excepción. – Nissan

5

Is AjaxRequest es un método de extensión. Entonces puede hacerlo de la siguiente manera usando 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); 
12

Aquí hay una solución que funciona usando RhinoMocks. Me he basado en una solución Moq he encontrado 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<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); 
} 
1

Para hacer IsAjaxRequest() para volver falsa durante la prueba de unidad que necesita para la configuración deseada y cabecera, así como valor de la colección petición tanto en su método de prueba como se indica 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"); 

La razón para establecer tanto se oculta en la aplicación de IsAjaxRequest() que se da a continuación:

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"))); 
} 

utiliza b oth request Colección y encabezado esta es la razón por la cual necesitamos crear la configuración para el encabezado y la colección de solicitudes.

Esto hará que la solicitud devuelva falso cuando no es una solicitud AJAX.para hacerla regresar verdad que puede hacer lo siguiente:

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

Para cualquier persona usando NSubstitute que era capaz de modificar las respuestas anteriores y hacer algo como esto ... (donde los detalles es el nombre del método de acción en el controlador)

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); 
2

Parece que busca esto,

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

Uso de controlador:

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