ما هو المطلوب في HttpContext للسماح بتنفيذ FormsAuthentication.SignOut()؟

StackOverflow https://stackoverflow.com/questions/1430180

  •  07-07-2019
  •  | 
  •  

سؤال

أحاول كتابة اختبار وحدة لطريقة تسجيل الخروج الخاصة بنا.من بين أمور أخرى ذلك FormsAuthentication.SignOut().ومع ذلك، فإنه يلقي System.NullReferenceException.

لقد خلقت وهمية. HttpContext (باستخدام Moq)، ولكن من الواضح أنه يفتقد شيئًا ما.

يحتوي السياق الوهمي الخاص بي على:

  • سخر HttpRequestBase على Request
  • سخر HttpResponseBase على Response
  • مع HttpCookieCollection على Request.Cookies وآخر على Response.Cookies
  • سخر IPrincipal على User

أنا أدرك أنه يمكنني اتباع طريق التغليف وحقن مادة فارغة FormsAuth الكائن المجمّع في مكانه، لكني أرغب حقًا في تجنب الملفات الثلاثة الإضافية فقط لإصلاح سطر واحد من التعليمات البرمجية.هذا وما زلت أشعر بالفضول للحصول على إجابة

لذلك سؤالي هو "ما هو المطلوب في HttpContext لكى يسمح FormsAuthentication.SignOut() to execute."

هل كانت مفيدة؟

المحلول

إليك رمز تسجيل الخروج.

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);
    }
}

يبدو أنك بحاجة إلى مثيل CookielessHelperClass.من المؤسف أنه داخلي ومختوم - لا توجد طريقة للسخرية منه إلا إذا كنت تستخدم TypeMock.+1 لاقتراحات المجمع :)

نصائح أخرى

يتم بالفعل طرح 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() ستنجح المكالمة الآن.

يمكنك دائمًا تغليف FormsAuthentication.SignOut() بطريقة أخرى وإيقافها/السخرية منها.

إنشاء واجهة IFormsAuthenticationWrap.

public interface IFormsAuthenticationWrap
{
    void SignOut();
}

قم بإنشاء فئة التفاف تطبق IFormsAuthenticationWrap

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();
    }

المجمع هو الطريق النظيف للذهاب.

لقد ذكرت في تعليق أن "هذا سيكون تطبيقًا كبيرًا جدًا"، وهذه حجة أخرى لاستخدام الغلاف وليس العكس.في التطبيقات الكبيرة، تريد أن يكون لديك تبعيات واضحة، وتريد إجراء الاختبارات بسهولة.

أنت تقوم بتداول التبعيات النظيفة التي يمكن إدخالها بسهولة عبر التبعيات الغامضة في الأعمال الداخلية لـ asp.net في اختباراتك.


على ملاحظة مختلفة: استخدم العاكس.أنا بصراحة لا أعرف التبعيات الداخلية لهذا الجزء المحدد من asp.net، ولكن يمكنك إزالة أي شكوك باستخدام العاكس.

لا تسخر من HttpContext، استخدم واحدًا حقيقيًا في اختباراتك.بهذه الطريقة لن تضطر إلى الاستهزاء بكل هذه الأشياء الخاصة بـ Http*.يمكنك استخدام إيفونا واختبر طريقتك مباشرة، دون الاستهزاء بكل هذه التبعيات والحصول على استثناءات غامضة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top