2009-06-09 11 views
146

J'ai un contrôleur en C# en utilisant le framework ASP.Net MVCComment faire pour simuler la demande sur le contrôleur dans ASP.Net MVC?

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

je suis arrivé quelques conseils sur moqueuse et espérait tester le code avec ce qui suit et 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); 

Cependant je garde obtenir cette erreur:

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

Puisque l'objet Request sur le contrôleur n'a pas setter. J'ai essayé de faire fonctionner ce test correctement en utilisant le code recommandé d'une réponse ci-dessous.

Cette utilisé Moq au lieu de RhinoMocks, et à utiliser Moq-je utiliser ce qui suit pour le même test:

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

mais l'erreur suivante:

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)

Encore une fois, il semble que je Impossible de définir l'en-tête de la demande. Comment définir cette valeur, dans RhinoMocks ou Moq?

+0

Remplacez Request.IsAjaxRequest par Request.IsAjaxRequest() –

+0

Mock Request.Headers ["X-Requested-With"] ou Request ["X-Requested-With"] au lieu de Request.IsAjaxRequest(). J'ai mis à jour ma question –

+0

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

Répondre

190

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

mise à jour:

Mock Request.Headers["X-Requested-With"] ou Request["X-Requested-With"] au lieu de Request.IsAjaxRequest().

+1

Je reçois le message "Type argument pour la méthode" ISetupGetter Moq.Mock .SetupGet .... ne peut pas être déduit de uage Essayez de spécifier explicitement les arguments de type ? Quel type dois-je mis « demande var = » pour que pour que cela fonctionne – Nissan

+0

juste mis à jour ma réponse - pas Request.IsAjaxRequest mais Request.IsAjaxRequest() Mettez à jour votre question trop –

+0

génère encore: Exception \t système. .ArgumentException: System.ArgumentException: configuration non valide sur un membre non redéfinissable: \t x => x.IsAjaxRequest() \t at Moq.Mock.ThrowIfCantOverride (Configuration de l'expression, MethodInfo methodInfo) – Nissan

3

Vous devez se moquer HttpContextBase et le mettre dans votre propriété ControllerContext, comme ça:

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

Ici vous pouvez voir comment se moquer de la collection Form, votre scénario sera similaire: Mocking the HttpRequest in ASP.NET MVC

+0

et qu'est-ce que mockedHttpContext doit être moqué? L'objet RequestContext dont il a besoin nécessite un objet HttpContextBase() dans le constructeur, et HttpContextBase() n'a pas de constructeur qui accepte les paramètres zéro. – Nissan

+0

Juste utiliser un cadre moqueur, ne pas essayer de construire ces objets directement ... –

+0

J'ai essayé: var mocks = new MockRepository(); var mockedhttpContext = mocks.DynamicMock (); var mockedHttpRequest = mocks.DynamicMock (); SetupResult.For (mockedhttpContext.Request) .Return (mockedHttpRequest); var controller = nouveau HomeController (Repository, LoginInfoProvider); controller.ControllerContext = nouveau mockedhttpContext, nouveau RouteData(), contrôleur); var résultat = controller.Index() as ViewResult; Cependant toujours obtenir la même exception levée. – Nissan

5

AjaxRequest est une méthode d'extension. Vous pouvez donc le faire de la façon suivante en utilisant 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

Voici une solution de travail utilisant RhinoMocks. Je l'ai basé sur une solution Moq j'ai trouvé à 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

Pour IsAjaxRequest() revenir faux lors de l'essai de l'appareil, vous devez configurer têtes de demande ainsi que la valeur de collecte de demande, aussi bien dans votre méthode d'essai comme indiqué ci-dessous:

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

La raison de la mise en place à la fois est caché dans la mise en œuvre de IsAjaxRequest() qui est donnée ci-dessous:

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

Il utilise b oth request Collection et en-tête c'est pourquoi nous devons créer une configuration pour Header et Request Collection.

cela fera la demande de retourner false quand ce n'est pas une requête ajax.pour le faire revenir vrai que vous pouvez effectuer les opérations suivantes:

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

Pour toute personne qui utilise NSubstitute j'ai pu modifier les réponses ci-dessus et faire quelque chose comme ça ... (où les détails est le nom de la méthode d'action sur le contrôleur)

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

on dirait que vous cherchez cela,

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

Utilisation dans le contrôleur:

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