Как издеваться над запросом на контроллере в ASP.Net MVC?
у меня есть контроллер в C# с помощью ASP.Net MVC framework
public class HomeController:Controller{
public ActionResult Index()
{
if (Request.IsAjaxRequest())
{
//do some ajaxy stuff
}
return View("Index");
}
}
Я получил несколько советов по издевательствам и надеялся протестировать код со следующим и 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);
однако я продолжаю получать эту ошибку:
исключение Система.Исключение ArgumentNullException: Система.Исключение ArgumentNullException : Значение не может быть null. Имя параметра: запрос на Система.Сеть.Mvc.AjaxRequestExtensions.IsAjaxRequest(HttpRequestBase запрос)
С
8 ответов:
используя упаковка:
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);
обновление:
Mock
Request.Headers["X-Requested-With"]
илиRequest["X-Requested-With"]
вместоRequest.IsAjaxRequest()
.
вот рабочее решение с использованием RhinoMocks. Я основал его на решении Moq, которое я нашел в 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); }
для тех, кто использует NSubstitute я смог изменить приведенные выше ответы и сделать что-то вроде этого... (где подробности-это имя метода действия на контроллере)
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);
является 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);
похоже, вы ищете этого,
var requestMock = new Mock<HttpRequestBase>(); requestMock.SetupGet(rq => rq["Age"]).Returns("2001");
использование в контроллере:
public ActionResult Index() { var age = Request["Age"]; //This will return 2001 }
вам нужно издеваться над HttpContextBase и поместить его в свойство ControllerContext, например:
controller.ControllerContext = new ControllerContext(mockedHttpContext, new RouteData(), controller);
сделать
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");
причина настройки обоих скрыта в реализации 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"))); }
он использует как коллекцию запросов, так и заголовок Вот почему нам нужно создать настройку как для заголовка, так и для коллекции запросов.
это сделает запрос на возврат false, если это не AJAX-запрос. чтобы вернуть значение true, вы можете сделать следующее:
_httpContext.SetupGet(x => x.Request["X-Requested-With"]).Returns("XMLHttpRequest");
Я нашел другой способ добавить объект HttpRequestMessage в ваш запрос во время веб-API следующим образом
[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 }