Что необходимо в HttpContext, чтобы разрешить выполнение FormsAuthentication.SignOut ()? - PullRequest
12 голосов
/ 16 сентября 2009

Я пытаюсь написать модульный тест для нашего метода выхода из системы.Среди прочего это FormsAuthentication.SignOut().Тем не менее, он выбрасывает System.NullReferenceException.

Я создал макет;HttpContext (используя Moq), но он явно чего-то не хватает.

Мой фиктивный контекст содержит:

  • Смеется HttpRequestBase на Request
  • Смеется HttpResponseBase на Response
  • С HttpCookieCollection на Request.Cookies и другим на Response.Cookies
  • С насмешкой IPrincipal на User

Я знаю, что могу пойти на оберткуНаправьте и вставьте пустой объект-оболочку FormsAuth на его место, но я бы очень хотел избежать трех дополнительных файлов, чтобы исправить только одну строку кода.Это и мне все еще интересно получить ответ

Поэтому мой вопрос " Что нужно в HttpContext, чтобы разрешить FormsAuthentication.SignOut() to execute."

Ответы [ 5 ]

20 голосов
/ 13 ноября 2012

Исключение 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() теперь будет успешным.

13 голосов
/ 16 сентября 2009

Вы всегда можете обернуть 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();
    }
8 голосов
/ 23 сентября 2009

Вот код для выхода.

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 для предложений обертки:)

2 голосов
/ 22 сентября 2009

Обертка - это чистый путь.

Вы упомянули в комментарии, что «это будет довольно большое приложение», это еще один аргумент в пользу использования оболочки, а не наоборот. В большом приложении вы хотите иметь четкие зависимости и хотите, чтобы тесты выполнялись легко.

Вы торгуете чистыми зависимостями, которые могут быть легко введены через неясные зависимости во внутреннюю работу asp.net в ваших тестах.


На другой ноте: Использовать отражатель . Честно говоря, я не знаю внутренних зависимостей этой конкретной части asp.net, но вы можете устранить любые сомнения с помощью рефлектора.

1 голос
/ 06 июля 2011

Не издевайтесь над HttpContext, используйте реальный в своих тестах. Таким образом, вам не нужно высмеивать все эти вещи Http *. Вы можете использовать Ivonna и протестировать свой метод напрямую, без насмешек над всеми этими зависимостями и получая загадочные исключения.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...