C# 单元测试表单SAuthentication.SignOut()中抛出错误
在运行我的单元测试方法时,我从sauthentication.SignOut()中得到错误。我曾经这样嘲笑过httpcontextC# 单元测试表单SAuthentication.SignOut()中抛出错误,c#,unit-testing,mocking,httprequest,forms-authentication,C#,Unit Testing,Mocking,Httprequest,Forms Authentication,在运行我的单元测试方法时,我从sauthentication.SignOut()中得到错误。我曾经这样嘲笑过httpcontext var httpRequest = new HttpRequest("", "http://localhost/", ""); var stringWriter = new StringWriter(); var httpResponse = new HttpResponse(stringWriter); var httpContext = new HttpCont
var httpRequest = new HttpRequest("", "http://localhost/", "");
var stringWriter = new StringWriter();
var httpResponse = new HttpResponse(stringWriter);
var httpContext = new HttpContext(httpRequest, httpResponse);
var sessionContainer = new HttpSessionStateContainer(
"id",
new SessionStateItemCollection(),
new HttpStaticObjectsCollection(),
10,
true,
HttpCookieMode.AutoDetect,
SessionStateMode.InProc,
false);
SessionStateUtility.AddHttpSessionStateToContext(httpContext, sessionContainer);
var controller = new AccountController();
var requestContext = new RequestContext(new HttpContextWrapper(httpContext), new RouteData());
controller.ControllerContext = new ControllerContext(requestContext, controller);
var actual = controller.Login(new CutomerModel() { Login = "admin", Password = "Password1" });
return httpContext;
在登录方法中
public ActionResult Login(CutomerModel obj)
{
FormsAuthentication.SignOut();
}
FormsAuthentication.SignOut()代码>抛出
“对象引用未设置为对象的实例。”
静态方法用于身份验证。注销
依赖于另一个静态成员HttpContext.Current
,该成员在单元测试期间不可用。将控制器与HttpContext紧密耦合。当前的
是静态的,这会导致代码很难测试。尽量避免耦合到静态调用
旁注:在为代码设置单元测试时遇到困难是一个明确的迹象,表明需要对其进行审查和重构
抽象FormsAuthentication
调用它们自己的关注点/接口,以便可以对它们进行模拟
public interface IFormsAuthenticationService {
void SignOut();
//...other code removed for brevity
}
生产代码可以包装实际调用,该调用应作为HttpContext工作。当前的
随后可用。确保DI容器知道如何解决依赖关系
public class FormsAuthenticationService : IFormsAuthenticationService {
public void SignOut() {
FormsAuthentication.SignOut();
}
//...other code removed for brevity
}
重构控制器,使其依赖于抽象而不是实现问题
public class AccountController : Controller {
//...other code removed for brevity.
private readonly IFormsAuthenticationService formsAuthentication;
public AccountController(IFormsAuthenticationService formsAuthentication) {
//...other arguments removed for brevity
this.formsAuthentication = formsAuthentication;
}
public ActionResult Login(CutomerModel obj) {
formsAuthentication.SignOut();
//...
return View();
}
//...other code removed for brevity.
}
和示例测试
注意:我用于模拟依赖项和断言结果
[TestMethod]
public void LoginTest() {
//Arrange
var model = new CutomerModel() { Login = "admin", Password = "Password1" };
var mockFormsAuthentication = new Mock<IFormsAuthenticationService>();
var controller = new AccountController(mockFormsAuthentication.Object);
//Act
var actual = controller.Login(model) as ViewResult;
//Assert (using FluentAssertions)
actual.Should().NotBeNull(because: "the actual result should have the returned view");
mockFormsAuthentication.Verify(m => m.SignOut(), Times.Once);
}
[TestMethod]
公共无效登录测试(){
//安排
var model=new-cutomemodel(){Login=“admin”,Password=“Password1”};
var mockFormsAuthentication=new Mock();
var控制器=新的AccountController(mockFormsAuthentication.Object);
//表演
var actual=controller.Login(model)作为ViewResult;
//断言(使用FluentAssertions)
actual.Should().NotBeNull(因为:“实际结果应该有返回的视图”);
mockFormsAuthentication.Verify(m=>m.SignOut(),Times.Once);
}
工作正常。谢谢