ASP.Net MVC에서 컨트롤러에서 요청을 조롱하는 방법?
ASP.Net MVC 프레임 워크를 사용하는 C # 컨트롤러가 있습니다.
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);
그러나이 오류가 계속 발생합니다.
예외 System.ArgumentNullException : System.ArgumentNullException : 값은 null 일 수 없습니다. 매개 변수 이름 : System.Web.Mvc.AjaxRequestExtensions.IsAjaxRequest (HttpRequestBase 요청)의 요청
Request
컨트롤러 의 오브젝트에 세터가 없기 때문입니다. 아래 답변에서 권장 코드를 사용 하여이 테스트를 올바르게 수행하려고했습니다.
이것은 RhinoMocks 대신 Moq를 사용했으며 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["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);
그러나 다음과 같은 오류가 발생합니다.
예외 System.ArgumentException : System.ArgumentException : 재정의 불가능한 멤버에 대한 잘못된 설정 : x => x.Headers [ "X-Requested-With"] at Moq.Mock.ThrowIfCantOverride (Expression setup, MethodInfo methodInfo)
다시 한 번, 요청 헤더를 설정할 수없는 것 같습니다. RhinoMocks 또는 Moq에서이 값을 어떻게 설정합니까?
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);
업데이트 :
모의 Request.Headers["X-Requested-With"]
또는 Request["X-Requested-With"]
대신 Request.IsAjaxRequest()
.
NSubstitute를 사용하는 사람이라면 위의 답변을 수정하고 다음과 같은 작업을 수행 할 수있었습니다 (여기서 Details는 컨트롤러의 Action 메소드 이름입니다)
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);
다음은 RhinoMocks를 사용하는 효과적인 솔루션입니다. http://thegrayzone.co.uk/blog/2010/03/mocking-request-isajaxrequest/ 에서 찾은 Moq 솔루션을 기반으로했습니다.
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);
}
Is AjaxRequest is an extension method. So you can do it the following way using 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);
Looks like you are looking for this,
var requestMock = new Mock<HttpRequestBase>();
requestMock.SetupGet(rq => rq["Age"]).Returns("2001");
Usage in Controller :
public ActionResult Index()
{
var age = Request["Age"]; //This will return 2001
}
You need to mock HttpContextBase and put it into your ControllerContext property, like that:
controller.ControllerContext =
new ControllerContext(mockedHttpContext, new RouteData(), controller);
To make IsAjaxRequest()
to return false during Unit test you need to setup Request Headers as well as request collection value both in your test method as given below:
_request.SetupGet(x => x.Headers).Returns(new System.Net.WebHeaderCollection { { "X-Requested-With", "NotAjaxRequest" } });
_request.SetupGet(x=>x["X-Requested-With"]).Returns("NotAjaxRequest");
The reason for setting up both is hidden in implementation of IsAjaxRequest() which is given below:
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")));
}
It uses both request Collection and header this is why we need to create setup for both Header and Request Collection.
this will make the request to return false when it is not a ajax request. to make it return true you can do the following:
_httpContext.SetupGet(x => x.Request["X-Requested-With"]).Returns("XMLHttpRequest");
I found other way to add a HttpRequestMessage object into your request during Web API as follow
[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
}
참고URL : https://stackoverflow.com/questions/970198/how-to-mock-the-request-on-controller-in-asp-net-mvc
'Programming' 카테고리의 다른 글
Xcode에서 메소드 참조 찾기 (0) | 2020.05.29 |
---|---|
특정 CSS를 조건부로 사용하기 위해 Rails 3.1 자산 파이프 라인 사용 (0) | 2020.05.28 |
화살표 함수 (공개 클래스 필드)를 클래스 메서드로 사용하는 방법은 무엇입니까? (0) | 2020.05.27 |
Webpack.config index.html을 dist 폴더에 복사하는 방법 (0) | 2020.05.26 |
가능한 두 테이블 중 하나에 MySQL 외래 키를 수행 할 수 있습니까? (0) | 2020.05.26 |