2009-06-09 6 views
146

Mam kontrolera w języku C# za pomocą ramy ASP.Net MVCJak wyśmiać żądanie na kontroler w ASP.Net MVC?

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

mam kilka porad na wyśmianie i ufałem przetestować kod z następujących i 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); 

jednak trzymam otrzymuję ten błąd:

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

Od obiektu Request na kontrolerze ma setter. Próbowałem uruchomić ten test poprawnie, używając zalecanego kodu z poniższej odpowiedzi.

ten stosowany Min zamiast RhinoMocks, aw użyciu MOQ używam następujących w tym samym teście:

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

ale pojawia się następujący błąd:

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)

Ponownie, wydaje się, że I nie można ustawić nagłówka żądania. Jak ustawić tę wartość w trybie RhinoMocks lub Moq?

+0

Zamień Request.IsAjaxRequest za pomocą Request.IsAjaxRequest() –

+0

Prośba Request.Headers ["X-Requested-With"] lub Request ["X-Requested-With"] zamiast Request.IsAjaxRequest(). Mam zaktualizowane moje pytanie –

+0

[spróbuj tego] (http://stackoverflow.com/questions/1228179/mocking-httpcontextbase-with-moq) – danfromisrael

Odpowiedz

190

Używanie 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); 

AKTUALIZACJA:

Mock Request.Headers["X-Requested-With"] lub Request["X-Requested-With"] zamiast Request.IsAjaxRequest().

+1

Otrzymuję komunikat "Argument Type dla metody" ISetupGetter Moq.Mock .SetupGet .... nie można wywołać z uśpienia. Spróbuj jawnie podać argumenty typu: ? Jakie mogę ustawić 'var request =' to jednak uzyskać to do pracy – Nissan

+0

Wystarczy aktualizowane moją odpowiedź - nie Request.IsAjaxRequest ale Request.IsAjaxRequest() Aktualizacja pytanie zbyt –

+0

nadal generuje: Wyjątek \t system. .ArgumentException: System.ArgumentException: niepoprawna konfiguracja nieprzenoszalnego elementu: \t x => x.IsAjaxRequest() \t at Moq.Mock.ThrowIfCantOverride (Konfiguracja wyrażeń, MethodInfo methodInfo) – Nissan

3

trzeba kpić HttpContextBase i umieścić ją na swojej własności ControllerContext, tak:

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

Tutaj można zobaczyć jak mock kolekcji Form, twój scenariusz będzie podobny: Mocking the HttpRequest in ASP.NET MVC

+0

i co wyśmiałobyHttpContext trzeba wyśmiać? tje Obiekt RequestContext wymaga obiektu HttpContextBase() w konstruktorze, a HttpContextBase() nie ma konstruktora, który akceptuje parametry zerowe. – Nissan

+0

Po prostu używaj szyderczego frameworka, nie próbuj budować tych obiektów bezpośrednio ... –

+0

Próbowałem: var mocks = new MockRepository(); var mockedhttpContext = mocks.DynamicMock (); var mockedHttpRequest = mocks.DynamicMock (); SetupResult.For (mockedhttpContext.Request) .Return (mockedHttpRequest); Sterownik var = new HomeController (Repository, LoginInfoProvider); controller.ControllerContext = new mockedhttpContext, new RouteData(), kontroler); var result = controller.Index() as ViewResult; Jednak nadal otrzymuję ten sam wyjątek zgłoszony. – Nissan

5

Czy AjaxRequest jest metodą rozszerzenia. Możesz zrobić to w następujący sposób, używając 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

Oto działające rozwiązanie z wykorzystaniem RhinoMocks. Mam go w oparciu o rozwiązania Min znalazłem w 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

Aby IsAjaxRequest() do return false podczas testów jednostkowych należy skonfigurować Nagłówki żądań, jak również wartość zażądać gromadzenia zarówno w metodzie badania, jak podano poniżej:

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

powodem utworzenia zarówno ukryte w realizacji IsAjaxRequest(), która znajduje się poniżej:

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

wykorzystuje b Inne żądanie Kolekcja i nagłówek dlatego musimy stworzyć konfigurację zarówno dla kolekcji nagłówków, jak i żądań.

spowoduje to, że żądanie zwrotu false, gdy nie jest to żądanie ajax.aby powrócić prawda można wykonać następujące czynności:

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

Dla osób korzystających NSubstitute udało mi się zmodyfikować powyższe odpowiedzi i zrobić coś takiego ... (gdzie Szczegóły to nazwa metody działania na kontrolerze)

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

Wygląda jak szukasz to

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

Wykorzystanie w kontrolerze:

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