MVC의 Mock HttpContext 테스트
7477 단어 context
moq 프레임워크는 강력한 시뮬레이션 능력을 제공하지만, HttpContext 대상을 시뮬레이션하려면 스스로 해야 한다.
이를 위해, 나는 스스로 방법을 써서 이 일을 완성했다.그 중에서도 Log4Net을 사용하여 작업 상황을 출력합니다.
/// <summary>
///
///
/// Request
/// AppRelativeCurrentExecutionFilePath,
/// ApplicationPath
/// PathInfo
/// Response
/// ApplyAppPathModifier
/// </summary>
/// <returns></returns>
private Moq.Mock<System.Web.HttpContextBase> CreateHttpContext()
{
log4net.ILog log = log4net.LogManager.GetLogger("CreateHttpContext");
string ApplicationPath = "/";
string PathInfo = "";
string AppRelativeCurrentExecutionFilePath = "~/";
var contextMock = new Moq.Mock<System.Web.HttpContextBase>();
contextMock
.Setup(c => c.Request.AppRelativeCurrentExecutionFilePath)
.Returns(AppRelativeCurrentExecutionFilePath)
.Callback(() => log.Info("Calling AppRelativeCurrentExecutionFilePath"));
contextMock
.Setup(c => c.Request.ApplicationPath)
.Returns(ApplicationPath)
.Callback(() => log.Info("Calling ApplicationPath"));
contextMock.Setup(rc => rc.Request.PathInfo)
.Returns(PathInfo)
.Callback(() => log.Info("Calling PathInfo"));
contextMock
.Setup(rc => rc.Response.ApplyAppPathModifier(Moq.It.IsAny<string>()))
.Returns((string s) => s)
.Callback((string s) => log.InfoFormat("Calling ApplyAppPathModifier: {0}.", s));
return contextMock;
}
이 방법은 이미 내가 필요로 하는 테스트를 완성할 수 있지만, 나는 그것을 추출하여 더욱 통용되는 Mock 방법을 얻을 수 있기를 바란다.
곧 나는 이 일이 이미 아주 오래 전에 Scott Hanselman에 한 번 소개되었는데, 그 중에서 심지어 서로 다른 Mock 프레임워크 아래의 제공 방법까지 썼다는 것을 발견했다.그러나 moq버전의 작가는 그가 아니라 다른 사람이다. Daniel Cazzulino. 이 글은 여기서 찾을 수 있다. http://www.hanselman.com/blog/ASPNETMVCSessionAtMix08TDDAndMvcMockHelpers.aspx, 그리고 Daniel Cazzulino의 블로그도 볼 수 있다. http://blogs.clariusconsulting.net/kzu/
그러나 그의 문장은 2008년에 쓴 것으로 정말 너무 낡았다.당시에는 MVC의 Preview2였는데, moq는 그때 이미 탄생했다. 내가 너무 과문한 것 같다.
우리의 주제로 돌아가서 이렇게 오랜 시간이 지나서 moq는 이미 약간의 변화가 생겼다. 최신의 moq 문법 수정을 사용한 후에 그의 코드가 테스트를 통과하지 못한 것을 발견했다.
나와 비교해 보니 Response에서 Apply App Path Modifier 방법에 대한 지원이 줄어들었고 증가한 후에 정상이 되었다.
다음은 수정된 코드입니다. 편의를 제공해 주십시오.
using System;
using System.Web;
using System.Text.RegularExpressions;
using System.IO;
using System.Collections.Specialized;
using System.Web.Mvc;
using System.Web.Routing;
using Moq;
namespace UnitTests
{
public static class MvcMockHelpers
{
public static HttpContextBase FakeHttpContext()
{
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>();
// Response ApplyAppPathModifier
response
.Setup(rsp => rsp.ApplyAppPathModifier(Moq.It.IsAny<string>()))
.Returns((string s) => s);
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);
return context.Object;
}
public static HttpContextBase FakeHttpContext(string url)
{
HttpContextBase context = FakeHttpContext();
context.Request.SetupRequestUrl(url);
return context;
}
// Controller
public static void SetFakeControllerContext(this Controller controller)
{
var httpContext = FakeHttpContext();
ControllerContext context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller);
controller.ControllerContext = context;
}
static string GetUrlFileName(string url)
{
if (url.Contains("?"))
return url.Substring(0, url.IndexOf("?"));
else
return url;
}
static NameValueCollection GetQueryStringParameters(string url)
{
if (url.Contains("?"))
{
NameValueCollection parameters = new NameValueCollection();
string[] parts = url.Split("?".ToCharArray());
string[] keys = parts[1].Split("&".ToCharArray());
foreach (string key in keys)
{
string[] part = key.Split("=".ToCharArray());
parameters.Add(part[0], part[1]);
}
return parameters;
}
else
{
return null;
}
}
// HttpRequestBase
public static void SetHttpMethodResult(this HttpRequestBase request, string httpMethod)
{
Mock.Get(request)
.Setup(req => req.HttpMethod)
.Returns(httpMethod);
}
//
public static void SetupRequestUrl(this HttpRequestBase request, string url)
{
log4net.ILog log = log4net.LogManager.GetLogger("CreateHttpContext");
if (url == null)
throw new ArgumentNullException("url");
if (!url.StartsWith("~/"))
throw new ArgumentException("Sorry, we expect a virtual url starting with \"~/\".");
var mock = Mock.Get(request);
mock.Setup(req => req.QueryString)
.Returns(GetQueryStringParameters(url));
mock.Setup(req => req.AppRelativeCurrentExecutionFilePath)
.Returns(GetUrlFileName(url))
.Callback(() => log.Info("Calling AppRelativeCurrentExecutionFilePath"));
mock.Setup(req => req.PathInfo)
.Returns(string.Empty);
}
}
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
WPF의 데이터 컨텍스트 및 자동 연결 소개 - iFour Technolab데이터 소스를 지정하는 몇 가지 방법이 있습니다. 바인딩에 Source 속성을 사용하고 DataContext를 상속할 수 있으며 ElementName 및 RelativeSource 속성도 개체 바인딩에 사용됩니다. ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.