我正在尝试为我们的注销方法编写单元测试.它除其他外 FormsAuthentication.SignOut()
.然而,它抛出了一个System.NullReferenceException
.
我创造了一个模拟; HttpContext
(使用Moq),但显然缺少一些东西.
我的模拟上下文包含:
一个嘲弄HttpRequestBase
的Request
一个嘲弄HttpResponseBase
的Response
随着HttpCookieCollection
上Request.Cookies
,另一个在Response.Cookies
一个嘲弄IPrincipal
的User
我知道我可以去包装路径并FormsAuth
在它的位置注入一个空的包装器对象,但我真的想避免这3个额外的文件来修复一行代码.那我和我仍然很好奇答案
所以我的问题是" 允许什么需要HttpContext
FormsAuthentication.SignOut() to execute.
"
在这种情况下,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{ { "supportsEmptyStringInCookieValue", "false" } } };
...... FormsAuthentication.SignOut()
现在电话会成功.
您始终可以将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(); }
这是注销的代码.
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 :)