Jid*_*jan 4 c# unit-testing forms-authentication mocking httprequest
在运行我的单元测试方法时,我收到错误 FormsAuthentication.SignOut()。我已经像这样嘲笑了 httpcontext
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;
Run Code Online (Sandbox Code Playgroud)
在登录方法中
public ActionResult Login(CutomerModel obj)
{
FormsAuthentication.SignOut();
}
Run Code Online (Sandbox Code Playgroud)
FormsAuthentication.SignOut(); 投掷
'你调用的对象是空的。'
静态方法FormsAuthentication.SignOut依赖于另一个静态成员HttpContext.Current,这在单元测试期间不可用。与HttpContext.Current静态控制器紧密耦合会导致代码很难测试。尽量避免与静态调用耦合。
旁注:为您的代码设置单元测试有困难是一个明确的迹象,表明它需要进行审查并且很可能需要重构。
AbstractFormsAuthentication调用它们自己的关注点/接口,以便它们可以被模拟。
public interface IFormsAuthenticationService {
void SignOut();
//...other code removed for brevity
}
Run Code Online (Sandbox Code Playgroud)
生产代码可以包装实际的调用,它应该可以正常工作HttpContext.Current。确保 DI 容器知道如何解决依赖关系。
public class FormsAuthenticationService : IFormsAuthenticationService {
public void SignOut() {
FormsAuthentication.SignOut();
}
//...other code removed for brevity
}
Run Code Online (Sandbox Code Playgroud)
重构控制器以依赖于抽象而不是实现问题。
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.
}
Run Code Online (Sandbox Code Playgroud)
和示例测试
注意:我使用Moq来模拟依赖项,使用FluentAssertions来断言结果。
[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);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
956 次 |
| 最近记录: |