1. ホーム
  2. c#

[解決済み] 単体テストでHttpContext.Current.Sessionを設定する

2022-04-18 18:54:39

質問

私はユニットテストを試みているウェブサービスがあります。 このサービスでは、いくつかの値を 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";

というヌル参照例外が発生します。 HttpContext.Current.Session はnullです。

ユニットテスト内で現在のセッションを初期化する方法はありますか?

どのように解決するのですか?

をモック化する必要がありました。 HttpContext を使用することで 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.CurrentHttpContextManager.Current で、同じメソッドにアクセスすることができます。それから、テストしているときにも HttpContextManager をモック化し、期待に応える

を使った例です。 モック :

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から期待される結果を追加し、Webサービスで利用できるようにすることができます。