1

次のようなある時点でいくつかの HttpModule を使用するコントローラー メソッド (ASP.NET MVC 4) をテストしたいと思います。

 var sessionToken = CreateSessionSecurityToken(CreatePrincipal(claims.ToList()), isPersistent);
            FederatedAuthentication.**SessionAuthenticationModule**.WriteSessionTokenToCookie(sessionToken);

モジュールは、SessionAuthenticationModule のサブクラスです。テスト アセンブリの app.config ファイルに必要な構成があります。

<system.web>
    <httpModules>
      <remove name="FormsAuthentication" />
      <add name="FormsSessionAuthentication" type="Security.FormsSessionAuthenticationModule, Security"/>
      <!--<add name="SessionAuthenticationModule"
           type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />-->
    </httpModules>
...

 <system.webServer>

    <validation validateIntegratedModeConfiguration="false" />

    <modules runAllManagedModulesForAllRequests="true" >
      <remove name="FormsAuthentication" />
      <add name="FormsSessionAuthentication" type="Security.FormsSessionAuthenticationModule, Security"/>
      <!--<add name="SessionAuthenticationModule"
           type="System.IdentityModel.Services.SessionAuthenticationModule, System.IdentityModel.Services, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" />-->
    </modules>

これは私が単体テストのコンテキストからやろうとしていることです:

            HttpContext.Current.ApplicationInstance = new HttpApplication();
            HttpApplication.RegisterModule(typeof (FormsSessionAuthenticationModule));
            Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(FormsSessionAuthenticationModule));

            var modules = HttpContext.Current.ApplicationInstance.Modules;

上記modulesの 2 つの方法を使用してコレクションを登録しようとすると、コレクションは空になります。

何か案は?

編集 - httpModule 実装を追加

public class FormsSessionAuthenticationModule : SessionAuthenticationModule
{
    protected bool IsSlidingExpiration { get; set; }
    protected TimeSpan Timeout { get; set; }
    protected string LoginUrl { get; set; }
    protected string CookieName { get; set; }
    protected string CookieDomain { get; set; }
    protected bool RequireSsl { get; set; }
    protected bool CachePrincipalOnServer { get; set; }

    protected override void InitializeModule(HttpApplication context)
    {
        base.InitializeModule(context);

        context.EndRequest += OnEndRequest;
    }

    protected override void InitializePropertiesFromConfiguration()
    {
        base.InitializePropertiesFromConfiguration();

        // read formsauth configuration
        IsSlidingExpiration = FormsAuthentication.SlidingExpiration;
        Timeout = FormsAuthentication.Timeout;
        LoginUrl = FormsAuthentication.LoginUrl;
        CookieName = FormsAuthentication.FormsCookieName;
        CookieDomain = FormsAuthentication.CookieDomain;
        RequireSsl = FormsAuthentication.RequireSSL;

        // read other configuration
        CachePrincipalOnServer = false;
        bool enabled;
        if (bool.TryParse(ConfigurationManager.AppSettings["CachePrincipalOnServer"], out enabled))
        {
            CachePrincipalOnServer = enabled;
        }

        // configure cookie handler
        CookieHandler.Name = CookieName;
        CookieHandler.Domain = CookieDomain;
        CookieHandler.RequireSsl = RequireSsl;
    }

    protected override void OnSessionSecurityTokenReceived(SessionSecurityTokenReceivedEventArgs e)
    {
        base.OnSessionSecurityTokenReceived(e);

        if (IsSlidingExpiration)
        {
            if (NeedsRenew(e.SessionToken))
            {
                e.SessionToken = CreateSessionSecurityToken(
                    e.SessionToken.ClaimsPrincipal,
                    e.SessionToken.Context,
                    DateTime.UtcNow,
                    DateTime.UtcNow.Add(Timeout),
                    e.SessionToken.IsPersistent);

                e.SessionToken.IsReferenceMode = CachePrincipalOnServer;
                e.ReissueCookie = true;
            }
        }
    }

    private void OnEndRequest(object sender, EventArgs e)
    {
        var httpApplication = sender as HttpApplication;
        if (httpApplication != null)
        {
            var context = httpApplication.Context;

            if (context.Response.StatusCode == 401)
            {
                var noRedirect = context.Items["NoRedirect"];

                if (noRedirect == null)
                {
                    var loginUrl = LoginUrl + "?returnUrl=" + HttpUtility.UrlEncode(context.Request.RawUrl, context.Request.ContentEncoding);
                    context.Response.Redirect(loginUrl);
                }
            }
        }
    }

    protected virtual bool NeedsRenew(SessionSecurityToken token)
    {
        DateTime utcNow = DateTime.UtcNow;

        TimeSpan span = utcNow - token.ValidFrom;
        TimeSpan span2 = token.ValidTo - utcNow;

        if (span2 > span)
        {
            return false;
        }

        return true;
    }
}
4

1 に答える 1

-1

あなたはこれをするべきではありません:)

モジュールの周りにラッパーを作成することをお勧めします。そして、コントローラーにラッパーを挿入します。そうすれば、テストでラッパーをモックできます。

public interface IAuthModule
{
   void WriteSessionTokenToCookie(Token sessionToken);
}

public class MyAuthModuleWrapper : IAuthModule
{
   public void WriteSessionTokenToCookie(Token sessionToken)
   {
       FederatedAuthentication.SessionAuthenticationModule.WriteSessionTokenToCookie(sessionToken);
   }
}

次に、IoC コンテナーを使用してアプリを接続していない場合は、コントローラーに貧弱なバージョンを使用できます (IoC を使用することを強くお勧めします)。

public class MyController : Controller
{
   private readonly IAuthModule _authModule;

   public MyController() : this(new MyAuthModuleWrapper()){}

   public MyController(IAuthModule authModule)
   {
      _authModule = authModule;
   }

   public ActionResult MyTestAction(string data)
   {
        // ... do whatever is here
        var sessionToken = CreateSessionSecurityToken(CreatePrincipal(claims.ToList()), isPersistent);
        _authModule.WriteSessionTokenToCookie(sessionToken);
        // ... do whatever else
   }
}

次に、テストで任意のモッキング フレームワークを使用できます。または、それが望ましくない場合は、IAuthToken の独自のスタブを作成して、それを使用して、コントローラーを構築することができます。

そして...あなたはすべて準備ができています。そのサードパーティ モジュールの登録に依存せずに、コントローラをテストできます。

于 2013-09-27T21:50:43.927 に答える