FormsAuthentication.SignOut()の実行を許可するには、HttpContextで何が必要ですか?
-
07-07-2019 - |
質問
ログアウトメソッドの単体テストを作成しようとしています。とりわけ FormsAuthentication.SignOut()
です。ただし、 System.NullReferenceException
がスローされます。
モックを作成しました。 HttpContext
(Moqを使用)ですが、明らかに何かが欠落しています。
私のモックコンテキストには以下が含まれます:
-
Request
の模擬 -
Response
の偽装 -
Request.Cookies
のHttpCookieCollection
とResponse.Cookies
の別の
-
User
での模擬
HttpRequestBase
HttpResponseBase
IPrincipal
ラッパールートに移動し、その場所に空の FormsAuth
ラッパーオブジェクトを挿入できることは承知していますが、1行を修正するためだけに3つの追加ファイルを避けたいと思います。コード。それと私はまだ答えが欲しいです
だから私の質問は" HttpContext
で FormsAuthentication.SignOut()を実行できるようにするために必要なもの
"
解決
ログアウトのコードは次のとおりです。
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 *のものをモックする必要はありません。 Ivonna を使用して、これらの依存関係をすべてモックし、不可解な例外を取得することなく、メソッドを直接テストできます。