Что нужно в HttpContext для выполнения FormsAuthentication.SignOut()?
Я пытаюсь написать unit test для нашего метода выхода. Среди прочего это FormsAuthentication.SignOut()
. Однако он выбрасывает System.NullReferenceException
.
Я создал макет; HttpContext
(используя Moq), но, очевидно, чего-то не хватает.
Мой макет содержит:
- Издевается
HttpRequestBase
на Request
- Издевается
HttpResponseBase
на Response
- С
HttpCookieCollection
на Request.Cookies
, а другой на Response.Cookies
- Издевается
IPrincipal
на User
Мне известно, что я мог бы пойти по маршруту обертки и ввести пустой объект FormsAuth
в этом месте, но мне бы очень хотелось избежать 3 дополнительных файлов, чтобы исправить одну строку кода. Это и я все еще интересуюсь ответом
Итак, мой вопрос: " Что необходимо в HttpContext
, чтобы разрешить FormsAuthentication.SignOut() to execute.
"
Ответы
Ответ 1
Вот код для выписки.
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
Исключение 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
Вы всегда можете перенести 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();
}
Ответ 4
Обертка - это чистый путь.
Вы упомянули в комментарии, что "это будет довольно большое приложение", это еще один аргумент, чтобы использовать обертку не наоборот. В большом приложении вы хотите иметь четкие зависимости, и вы хотите, чтобы тесты выполнялись легко.
Вы торгуете чистыми зависимостями, которые можно легко вводить по неясным зависимостям во внутренние действия asp.net в ваших тестах.
В другом примечании: Использовать рефлектор. Я честно не знаю внутренних зависимостей этой конкретной части asp.net, но вы можете устранить любые сомнения с помощью отражателя.
Ответ 5
Не издевайтесь над HttpContext, используйте реальный тест. Таким образом, вам не нужно издеваться над всеми этими материалами Http *. Вы можете использовать Ivonna и протестировать свой метод напрямую, не издеваясь над всеми этими зависимостями и получая загадочные исключения.