1. ホーム
  2. c#

[解決済み】テストのInitメソッドでHttpContext.Currentをモックする

2022-04-20 10:21:39

質問

私は、構築したASP.NET MVCアプリケーションにユニットテストを追加しようとしています。 私のユニットテストでは、次のコードを使用しています。

[TestMethod]
public void IndexAction_Should_Return_View() {
    var controller = new MembershipController();
    controller.SetFakeControllerContext("TestUser");

    ...
}

以下のヘルパーを使用して、コントローラのコンテキストをモックします。

public static class FakeControllerContext {
    public static HttpContextBase FakeHttpContext(string username) {
        var context = new Mock<HttpContextBase>();

        context.SetupGet(ctx => ctx.Request.IsAuthenticated).Returns(!string.IsNullOrEmpty(username));

        if (!string.IsNullOrEmpty(username))
            context.SetupGet(ctx => ctx.User.Identity).Returns(FakeIdentity.CreateIdentity(username));

        return context.Object;
    }

    public static void SetFakeControllerContext(this Controller controller, string username = null) {
        var httpContext = FakeHttpContext(username);
        var context = new ControllerContext(new RequestContext(httpContext, new RouteData()), controller);
        controller.ControllerContext = context;
    }
}

このテストクラスは、以下のようなベースクラスを継承しています。

[TestInitialize]
public void Init() {
    ...
}

このメソッドの内部で、(私がコントロールできない)ライブラリを呼び出し、次のコードを実行しようとします。

HttpContext.Current.User.Identity.IsAuthenticated

さて、問題がお分かりいただけたでしょうか。 コントローラに対して偽のHttpContextを設定しましたが、このベースのInitメソッドには設定されていません。 ユニットテスト/モッキングは私にとって非常に新しいものなので、これを正しく行うことを確認したいと思います。 HttpContextをモックアウトして、コントローラやInitメソッドで呼び出されるライブラリで共有するには、どのような方法があるでしょうか?

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

HttpContext.Current のインスタンスを返します。 System.Web.HttpContext を拡張しない。 System.Web.HttpContextBase . HttpContextBase に対応するため、後から追加されました。 HttpContext はモックしにくい。この2つのクラスは基本的に無関係です ( HttpContextWrapper は両者間のアダプタとして使用されます)。

幸いです。 HttpContext を置き換えるには、それ自体が十分にフェイク可能です。 IPrincipal (ユーザー)と IIdentity .

次のコードは、コンソールアプリケーションでも期待通りに実行されます。

HttpContext.Current = new HttpContext(
    new HttpRequest("", "http://tempuri.org", ""),
    new HttpResponse(new StringWriter())
    );

// User is logged in
HttpContext.Current.User = new GenericPrincipal(
    new GenericIdentity("username"),
    new string[0]
    );

// User is logged out
HttpContext.Current.User = new GenericPrincipal(
    new GenericIdentity(String.Empty),
    new string[0]
    );