단위 테스트를 시도하는 웹 서비스가 있습니다. 서비스에서 다음 HttpContext
과 같은 여러 값을 가져옵니다 .
m_password = (string)HttpContext.Current.Session["CustomerId"];
m_userID = (string)HttpContext.Current.Session["CustomerUrl"];
단위 테스트에서 간단한 작업자 요청을 사용하여 컨텍스트를 작성합니다.
SimpleWorkerRequest request = new SimpleWorkerRequest("", "", "", null, new StringWriter());
HttpContext context = new HttpContext(request);
HttpContext.Current = context;
그러나 값을 설정하려고 할 때마다 HttpContext.Current.Session
HttpContext.Current.Session["CustomerId"] = "customer1";
HttpContext.Current.Session["CustomerUrl"] = "customer1Url";
null이라는 예외 참조 HttpContext.Current.Session
가 나타납니다.
단위 테스트 내에서 현재 세션을 초기화하는 방법이 있습니까?
답변
우리는 단위 테스트뿐만 아니라 응용 프로그램 내에서 HttpContext
a를 사용 HttpContextManager
하고 공장을 호출 하여 조롱해야했습니다.
public class HttpContextManager
{
private static HttpContextBase m_context;
public static HttpContextBase Current
{
get
{
if (m_context != null)
return m_context;
if (HttpContext.Current == null)
throw new InvalidOperationException("HttpContext not available");
return new HttpContextWrapper(HttpContext.Current);
}
}
public static void SetCurrentContext(HttpContextBase context)
{
m_context = context;
}
}
그런 다음에 어떤 통화를 대체 할 것이다 HttpContext.Current
과 HttpContextManager.Current
같은 방법에 액세스 할 수 있습니다. 그런 다음 테스트 할 때 HttpContextManager
기대치에 액세스 하고 조롱 할 수도 있습니다.
다음은 Moq 사용 예입니다 .
private HttpContextBase GetMockedHttpContext()
{
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>();
var user = new Mock<IPrincipal>();
var identity = new Mock<IIdentity>();
var urlHelper = new Mock<UrlHelper>();
var routes = new RouteCollection();
MvcApplication.RegisterRoutes(routes);
var requestContext = new Mock<RequestContext>();
requestContext.Setup(x => x.HttpContext).Returns(context.Object);
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);
context.Setup(ctx => ctx.User).Returns(user.Object);
user.Setup(ctx => ctx.Identity).Returns(identity.Object);
identity.Setup(id => id.IsAuthenticated).Returns(true);
identity.Setup(id => id.Name).Returns("test");
request.Setup(req => req.Url).Returns(new Uri("http://www.google.com"));
request.Setup(req => req.RequestContext).Returns(requestContext.Object);
requestContext.Setup(x => x.RouteData).Returns(new RouteData());
request.SetupGet(req => req.Headers).Returns(new NameValueCollection());
return context.Object;
}
그런 다음 단위 테스트에서 사용하려면 Test Init 메소드 내에서 이것을 호출하십시오.
HttpContextManager.SetCurrentContext(GetMockedHttpContext());
그런 다음 위의 방법으로 웹 서비스에서 사용할 수있을 것으로 예상되는 Session의 예상 결과를 추가 할 수 있습니다.
답변
다음 HttpContext
과 같이 새로운 것을 만들어 “가짜”를 만들 수 있습니다 .
그 코드를 가져 와서 정적 도우미 클래스에 넣었습니다.
public static HttpContext FakeHttpContext()
{
var httpRequest = new HttpRequest("", "http://example.com/", "");
var stringWriter = new StringWriter();
var httpResponse = new HttpResponse(stringWriter);
var httpContext = new HttpContext(httpRequest, httpResponse);
var sessionContainer = new HttpSessionStateContainer("id", new SessionStateItemCollection(),
new HttpStaticObjectsCollection(), 10, true,
HttpCookieMode.AutoDetect,
SessionStateMode.InProc, false);
httpContext.Items["AspSession"] = typeof(HttpSessionState).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null, CallingConventions.Standard,
new[] { typeof(HttpSessionStateContainer) },
null)
.Invoke(new object[] { sessionContainer });
return httpContext;
}
또는 대신 새로운 구성하기 위해 반사를 사용하는 HttpSessionState
인스턴스를, 당신은 당신을 첨부 할 수 있습니다 HttpSessionStateContainer
받는 사람 HttpContext
(브렌트 M. 맞춤법의 의견에 따라) :
SessionStateUtility.AddHttpSessionStateToContext(httpContext, sessionContainer);
그런 다음 단위 테스트에서 다음과 같이 호출 할 수 있습니다.
HttpContext.Current = MockHelper.FakeHttpContext();
답변
Milox 솔루션 은 허용되는 IMHO보다 낫지 만 querystring으로 URL을 처리 할 때이 구현에 문제가있었습니다 .
URL에서 제대로 작동하고 리플렉션을 피하기 위해 변경했습니다.
public static HttpContext FakeHttpContext(string url)
{
var uri = new Uri(url);
var httpRequest = new HttpRequest(string.Empty, uri.ToString(),
uri.Query.TrimStart('?'));
var stringWriter = new StringWriter();
var httpResponse = new HttpResponse(stringWriter);
var httpContext = new HttpContext(httpRequest, httpResponse);
var sessionContainer = new HttpSessionStateContainer("id",
new SessionStateItemCollection(),
new HttpStaticObjectsCollection(),
10, true, HttpCookieMode.AutoDetect,
SessionStateMode.InProc, false);
SessionStateUtility.AddHttpSessionStateToContext(
httpContext, sessionContainer);
return httpContext;
}
답변
나는 얼마전에 이것에 대해 뭔가를 걱정한다.
MVC3 .NET에서 HttpContext.Current.Session의 단위 테스트
도움이 되길 바랍니다.
[TestInitialize]
public void TestSetup()
{
// We need to setup the Current HTTP Context as follows:
// Step 1: Setup the HTTP Request
var httpRequest = new HttpRequest("", "http://localhost/", "");
// Step 2: Setup the HTTP Response
var httpResponce = new HttpResponse(new StringWriter());
// Step 3: Setup the Http Context
var httpContext = new HttpContext(httpRequest, httpResponce);
var sessionContainer =
new HttpSessionStateContainer("id",
new SessionStateItemCollection(),
new HttpStaticObjectsCollection(),
10,
true,
HttpCookieMode.AutoDetect,
SessionStateMode.InProc,
false);
httpContext.Items["AspSession"] =
typeof(HttpSessionState)
.GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null,
CallingConventions.Standard,
new[] { typeof(HttpSessionStateContainer) },
null)
.Invoke(new object[] { sessionContainer });
// Step 4: Assign the Context
HttpContext.Current = httpContext;
}
[TestMethod]
public void BasicTest_Push_Item_Into_Session()
{
// Arrange
var itemValue = "RandomItemValue";
var itemKey = "RandomItemKey";
// Act
HttpContext.Current.Session.Add(itemKey, itemValue);
// Assert
Assert.AreEqual(HttpContext.Current.Session[itemKey], itemValue);
}
답변
MVC 프레임 워크를 사용하는 경우 이것이 작동합니다. Milox의 FakeHttpContext를 사용 하고 몇 줄의 코드를 추가했습니다. 아이디어는이 게시물에서 나왔습니다.
이것은 MVC 5에서 작동하는 것 같습니다. 이전 버전의 MVC에서는 이것을 시도하지 않았습니다.
HttpContext.Current = MockHttpContext.FakeHttpContext();
var wrapper = new HttpContextWrapper(HttpContext.Current);
MyController controller = new MyController();
controller.ControllerContext = new ControllerContext(wrapper, new RouteData(), controller);
string result = controller.MyMethod();
답변
FakeHttpContext 시도 할 수 있습니다 :
using (new FakeHttpContext())
{
HttpContext.Current.Session["CustomerId"] = "customer1";
}
답변
asp.net Core / MVC 6 rc2에서 HttpContext
var SomeController controller = new SomeController();
controller.ControllerContext = new ControllerContext();
controller.ControllerContext.HttpContext = new DefaultHttpContext();
controller.HttpContext.Session = new DummySession();
rc 1은
var SomeController controller = new SomeController();
controller.ActionContext = new ActionContext();
controller.ActionContext.HttpContext = new DefaultHttpContext();
controller.HttpContext.Session = new DummySession();
https://stackoverflow.com/a/34022964/516748
사용을 고려하십시오 Moq
new Mock<ISession>();
