代码之家  ›  专栏  ›  技术社区  ›  jeef3

在httpContext中,允许执行FormsAuthentication.Signout()需要什么?

  •  12
  • jeef3  · 技术社区  · 16 年前

    我正在为我们的注销方法编写一个单元测试。除此之外 FormsAuthentication.SignOut() . 但是,它抛出了一个 System.NullReferenceException .

    我做了一个模型; HttpContext (使用moq),但它显然缺少一些东西。

    我的模拟上下文包含:

    • 嘲弄的 HttpRequestBase Request
    • 嘲弄的 HttpResponseBase Response
    • 用一个 HttpCookieCollection Request.Cookies 另一个 Response.Cookies
    • 嘲弄的 IPrincipal User

    我知道我可以走包装机的路线,注入一个空的 FormsAuth 包装器对象在它的位置,但我真的想避免3个额外的文件只是为了修复一行代码。我还是很想知道答案

    所以我的问题是” 需要什么 请求上下文 允许 FormsAuthentication.SignOut() to execute.

    5 回复  |  直到 11 年前
        1
  •  8
  •   womp    16 年前

    这是签退的代码。

    public static void SignOut()
    {
        Initialize();
        HttpContext current = HttpContext.Current;
        bool flag = current.CookielessHelper.DoesCookieValueExistInOriginal('F');
        current.CookielessHelper.SetCookieValue('F', null);
        if (!CookielessHelperClass.UseCookieless(current, false, CookieMode) || current.Request.Browser.Cookies)
        {
            string str = string.Empty;
            if (current.Request.Browser["supportsEmptyStringInCookieValue"] == "false")
            {
                str = "NoCookie";
            }
            HttpCookie cookie = new HttpCookie(FormsCookieName, str);
            cookie.HttpOnly = true;
            cookie.Path = _FormsCookiePath;
            cookie.Expires = new DateTime(0x7cf, 10, 12);
            cookie.Secure = _RequireSSL;
            if (_CookieDomain != null)
            {
                cookie.Domain = _CookieDomain;
            }
            current.Response.Cookies.RemoveCookie(FormsCookieName);
            current.Response.Cookies.Add(cookie);
        }
        if (flag)
        {
            current.Response.Redirect(GetLoginPage(null), false);
        }
    }
    

    看起来您需要一个CookeIElessHelperClass实例。太糟糕了,它是内部密封的——除非你用的是typemock,否则无法模仿它。+包装建议:1)

        2
  •  19
  •   Gracie Omoplata    13 年前

    在这种情况下,nullReferenceException实际上正由调用引发:

    current.Request.Browser["supportsEmptyStringInCookieValue"]
    

    您可以通过调用以下命令来测试此断言:

    HttpContext.Current.Request.Browser.SupportsEmptyStringInCookieValue
    

    …这也将返回NullReferenceException。与接受的回答相反,如果您尝试拨打:

    CookielessHelperClass.UseCookieless(current, false, CookieMode)
    

    …从即时窗口返回,不会出错。

    您可以这样修复异常:

    HttpContext.Current.Request.Browser = new HttpBrowserCapabilities() { Capabilities = new Dictionary<string, string> { { "supportsEmptyStringInCookieValue", "false" } } };
    

    …… FormsAuthentication.SignOut() 呼叫现在将成功。

        3
  •  13
  •   Vadim    16 年前

    您始终可以将formsAuthentication.signout()包装到另一个方法中,并对其进行存根/模拟。

    创建iformsAuthenticationWrap接口。

    public interface IFormsAuthenticationWrap
    {
        void SignOut();
    }
    

    创建实现IFormsAuthenticationWrap的Wrap类

    public class FormsAuthenticationWrap : IFormsAuthenticationWrap
    {
        public void SignOut()
        {
            FormsAuthentication.SignOut();
        }
    }
    

    你的主叫课看起来是这样的:

    public class LogOutClass
    {
        private readonly IFormsAuthenticationWrap _formsAuthentication;
    
        public LogOutClass() : this (new FormsAuthenticationWrap())
        {
        }
    
        public LogOutClass(IFormsAuthenticationWrap formsAuthentication)
        {
            _formsAuthentication = formsAuthentication;
        }
    
        public void LogOutMethod()
        {
            // Code before SignOut
    
            _formsAuthentication.SignOut();
    
            // Code after SignOut
        }
    }
    

    现在让我们开始测试。你可以用moq做存根/模拟,但我将在这里演示你如何手动完成。 创建存根/模拟类:

    public class FormsAuthenticationStub : IFormsAuthenticationWrap
    {
        public void SignOut()
        {
        }
    }
    

    最后一次写测试:

        [TestMethod]
        public void TestLogOutMethod()
        {
            var logOutClass = new LogOutClass(new FormsAuthenticationStub());
            logOutClass.LogOutMethod();
        }
    
        4
  •  2
  •   eglasius    16 年前

    包装是干净的方法。

    您在评论中提到“这将是一个相当大的应用程序”,这是使用包装器的另一个论点,而不是相反的。在一个大的应用程序中,您希望有清晰的依赖关系,并且您希望测试可以很容易地完成。

    您正在交换干净的依赖项,这些依赖项可以很容易地注入到测试中ASP.NET内部工作的模糊依赖项之上。


    另一方面: 使用反射镜 .老实说,我不知道ASP.NET这一特定部分的内部依赖性,但您可以通过Reflector消除任何疑问。

        5
  •  1
  •   ulu    15 年前

    不要模仿httpcontext,在测试中使用真实的。这样你就不必嘲笑所有这些HTTP*的东西了。你可以使用 Ivonna 并且直接测试您的方法,而不模拟所有这些依赖项并获得神秘的异常。

    推荐文章