ASP.NET MVC : UrlHelper를 사용하는 단위 테스트 컨트롤러


170

내 컨트롤러 작업 중 하나, Ajax 요청에서 호출되는 작업은 URL을 클라이언트 측으로 반환하여 리디렉션을 수행 할 수 있습니다. 사용 Url.RouteUrl(..)하고 있으며 단위 테스트 중에 Controller.Url매개 변수가 미리 채워져 있지 않아 실패합니다 .

나는 그루터기를 시도하는 다른 사람의 사이에서 많은 것들을 시도 UrlHelper수동으로 생성, (실패) UrlHelperA를 RequestContext스텁이 그 HttpContextBase(A에 실패 RouteCollection.GetUrlWithApplicationPath호출).

Google을 검색했지만 주제에서 거의 아무것도 찾지 못했습니다. Url.RouteUrl내 컨트롤러 작업에서 엄청나게 바보 같은 일을하고 있습니까? 더 쉬운 방법이 있습니까?

더 나쁘게 만들기 위해 단위 테스트에서 반환 된 URL을 테스트 할 수 있기를 원합니다. 실제로 올바른 경로로 리디렉션되는 것을 알고 싶지만 URL 대신 URL을 반환하기 때문에 라우트에서 해결 된 URL을 제어하고 싶습니다 (예 : 스텁을 사용하여 RouteCollection).하지만 테스트를 시작하게되어 기쁩니다.

답변:


202

다음은 비슷한 경우 (제어기에서 Url.RouteUrl 사용)에 대한 내 테스트 중 하나입니다 (xUnit + Moq).

도움이 되었기를 바랍니다:

var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);

var request = new Mock<HttpRequestBase>(MockBehavior.Strict);
request.SetupGet(x => x.ApplicationPath).Returns("/");
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
request.SetupGet(x => x.ServerVariables).Returns(new System.Collections.Specialized.NameValueCollection());

var response = new Mock<HttpResponseBase>(MockBehavior.Strict);
response.Setup(x => x.ApplyAppPathModifier("/post1")).Returns("http://localhost/post1");

var context = new Mock<HttpContextBase>(MockBehavior.Strict);
context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);

var controller = new LinkbackController(dbF.Object);
controller.ControllerContext = new ControllerContext(context.Object, new RouteData(), controller);
controller.Url = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);

2
당분간 나는 UrlHelper에 대한 호출을 추상화하여 솔루션을 가로 챌 수있는 솔루션을 사용했습니다. 그러나 스 니펫 덕분에 Request / Response / ControllerContext를 올바르게 조롱하는 방법을 알아내는 데 많은 시간을 절약 할 수 있습니다.
efdee

@ eu-ge-ne 답변에 감사드립니다. 나에게 많은 도움이되었습니다. 나는 UpdateModel 사용하는 formcollection 매개 변수를 사용하는 몇 가지 더 MOQ의 설정 포함 시켰습니다
jebcrum

16
+1 우수 팁 : 나는 이것을 MockHelper로 사용하고 responseAppSetupModifier에 대한 response.Setup을 다음과 같이 변경하십시오 : response.Setup (x => x.ApplyAppPathModifier (Moq.It.IsAny <String> ()))). ) => url); 추악하지만 반환 된 값을 하드 코딩하는 대신 직렬화 된 객체를 URL로 인코딩 된 형식으로 다시 가져옵니다.
eduncan911

그것은 부분적으로 나를 위해 작동합니다. Controller / Action 대신 Controller /를 얻는 이유는 무엇입니까? 테스트가 동일하지 않아서 동일한 라우팅 값을 등록했기 때문에 테스트에 실패했습니다. 매우 이상합니다 ...
Nick

3
ApplyAppPathModifier부분은 UrlHelper의 중요한 부분입니다
Chris S

37

eu-ge-ne에서 수정 된 구현. 응용 프로그램에 정의 된 경로를 기반으로 생성 된 링크를 반환합니다. eu-ge-ne의 예제는 항상 고정 된 응답을 반환했습니다. 아래 방법을 사용하면 올바른 작업 / 컨트롤러 및 경로 정보가 UrlHelper로 전달되는지 테스트 할 수 있습니다. UrlHelper에 대한 호출을 테스트하는 경우 원하는 것입니다.

var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();

context.Setup(ctx => ctx.Request).Returns(request.Object);
context.Setup(ctx => ctx.Response).Returns(response.Object);
context.Setup(ctx => ctx.Session).Returns(session.Object);
context.Setup(ctx => ctx.Server).Returns(server.Object);

request.SetupGet(x => x.ApplicationPath).Returns("/");
request.SetupGet(x => x.Url).Returns(new Uri("http://localhost/a", UriKind.Absolute));
request.SetupGet(x => x.ServerVariables).Returns(new NameValueCollection());

response.Setup(x => x.ApplyAppPathModifier(It.IsAny<string>())).Returns<string>(x => x);

context.SetupGet(x => x.Request).Returns(request.Object);
context.SetupGet(x => x.Response).Returns(response.Object);

var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
var helper = new UrlHelper(new RequestContext(context.Object, new RouteData()), routes);

12

이 게시물은 HttpContextBase 클래스를 조롱하려는 경우 유용 할 수 있습니다.

http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx


쿨, 이것은 도움이되었지만 헬퍼가 터지는 것을 막기 위해 FakeHttpContext 메소드에 약간의 코드를 추가해야했습니다. context.Setup (ctx => ctx.Request.ApplicationPath) .Returns ( "/ AntiBlowup"); 또한 코드를 리팩터링하여 최신 Setup () 구문을 사용합니다. 감사.
RichardOD

2

@ eu-ge-ne의 답변을 작성하면 많은 도움이되었습니다.

리디렉션을 수행하고 FormCollection 매개 변수를 사용하여 UpdateModel 호출을 수행 한 ActionResult가 있습니다. UpdateModel ()이 작동하려면 Mocked HttpRequestBase에 이것을 추가해야했습니다.

FormCollection collection = new FormCollection();
collection["KeyName"] = "KeyValue";

request.Setup(x => x.Form).Returns(collection);
request.Setup(x => x.QueryString).Returns(new NameValueCollection());

리디렉션 된 URL이 올바른지 테스트하려면 다음을 수행하십시오.

RedirectResult result = controller.ActionName(modelToSubmit, collection) as RedirectResult;
Assert.AreEqual("/Expected/URL", result.Url);

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.