我有一个控制器操作,如果用户已经登录(User.Identity.IsAuthenticated
),它会自动重定向到新页面。为此场景编写单元测试以确保重定向发生的最佳方式是什么?如何对使用Controller.User变量的控制器操作进行单元测试?
8
A
回答
14
我一直在使用下面的Mock和Moq来允许在我的单元测试中设置各种条件。首先,HttpContextBase模拟:
public static Mock<HttpContextBase> GetHttpContextMock(bool isLoggedIn)
{
var context = new Mock<HttpContextBase>();
var request = new Mock<HttpRequestBase>();
var response = new Mock<HttpResponseBase>();
var session = new Mock<HttpSessionStateBase>();
var server = new Mock<HttpServerUtilityBase>();
var principal = AuthenticationAndAuthorization.GetPrincipleMock(isLoggedIn);
context.SetupGet(c => c.Request).Returns(request.Object);
context.SetupGet(c => c.Response).Returns(response.Object);
context.SetupGet(c => c.Session).Returns(session.Object);
context.SetupGet(c => c.Server).Returns(server.Object);
context.SetupGet(c => c.User).Returns(principal.Object);
return context;
}
每个属性可能提供一个有用的模拟在这里成立。这样一来,如果我需要添加类似引荐,我可以只使用:
Mock.Get(controller.Request).Setup(s => s.UrlReferrer).Returns(new Uri("http://blah.com/");
的“GetPrincipleMock”的方法就是建立用户。它看起来像这样:
public static Mock<IPrincipal> GetPrincipleMock(bool isLoggedIn)
{
var mock = new Mock<IPrincipal>();
mock.SetupGet(i => i.Identity).Returns(GetIdentityMock(isLoggedIn).Object);
mock.Setup(i => i.IsInRole(It.IsAny<string>())).Returns(false);
return mock;
}
public static Mock<IIdentity> GetIdentityMock(bool isLoggedIn)
{
var mock = new Mock<IIdentity>();
mock.SetupGet(i => i.AuthenticationType).Returns(isLoggedIn ? "Mock Identity" : null);
mock.SetupGet(i => i.IsAuthenticated).Returns(isLoggedIn);
mock.SetupGet(i => i.Name).Returns(isLoggedIn ? "testuser" : null);
return mock;
}
现在,在测试我的控制器的设置是这样的:
var controller = new ProductController();
var httpContext = GetHttpContextMock(true); //logged in, set to false to not be logged in
ControllerContext controllerContext = new ControllerContext(httpContext.Object, new RouteData(), controller);
controller.ControllerContext = controllerContext;
这是冗长设置的一点点,但一旦你有一切就绪,测试各种的条件变得更容易。
7
这不是最简单的事情,但它可以做到。 User属性只是委托给Controller.HttpContext.User。两者都是非虚拟的只读属性,所以你不能对它们做任何事情。但是,Controller.HttpContext委托给ControllerBase.ControllerContext,它是一个可写属性。
因此,在执行被测系统(SUT)之前,您可以将Test Double HttpContextBase分配给Controller.ControllerContext。使用Moq,它看起来像这样:
var user = new GenericPrincipal(new GenericIdentity(string.Empty), null);
var httpCtxStub = new Mock<HttpContextBase>();
httpCtxStub.SetupGet(ctx => ctx.User).Returns(user);
var controllerCtx = new ControllerContext();
controllerCtx.HttpContext = httpCtxStub.Object;
sut.ControllerContext = controllerCtx;
然后调用您的操作并验证返回结果是否为RedirectResult。
此测试利用了隐式知识,当您使用空名称创建GenericIdentity时,它将为IsAuthenticated返回false。您可以考虑通过使用Mock<IIdentity>
来更明确地进行测试。
相关问题
- 1. 如何对使用springSecurityService的控制器进行单元测试?
- 2. 如何对zend动作控制器进行单元测试?
- 3. Controller.User是空单元测试
- 4. 使用依赖注入对控制器进行单元测试
- 5. 如何对此控制器进行单元测试?
- 6. 如何在mvc控制器中进行会话变量的单元测试
- 7. 如何对使用DotNetOpenId的ASP.NET MVC控制器进行单元测试?
- 8. 如何对使用环境变量的装饰器进行单元测试?
- 9. 您如何使用EF SaveChanges对MVC控制器进行单元测试
- 10. 使用起订量测试控制器操作方法的单元
- 11. 如何对使用ServiceStack的JsonServiceClient()的ASP.NET MVC操作进行单元测试?
- 12. 单元测试控制器调用IsAjaxRequest()的操作
- 13. 使用DB单元进行弹簧控制器集成测试
- 14. 使用控制器参数进行单元测试
- 15. 如何测试'新'控制器操作?
- 16. 当使用automapper时如何对单元测试控制器?
- 17. 如何使用$ scope对单元测试角控制器$ on?
- 18. 如何在操作中对具有私有方法的ASP.Net MVC控制器进行单元测试?
- 19. 如何使用System.Windows.Threading.Dispatcher对单元进行单元测试
- 20. Asp.Net的mvc单元测试的控制器操作
- 21. 使用Rspec进行控制器测试
- 22. 我的单元测试是不是抓我控制器操作
- 23. 单元测试控制器
- 24. 单元测试控制器
- 25. MVC控制器单元测试写作
- 26. 如何对wxPython进行单元测试?
- 27. 如何对rxjs5进行单元测试?
- 28. 如何对Response.Redirect进行单元测试?
- 29. 如何对IDataErrorInfo进行单元测试?
- 30. 如何对Xtext进行单元测试
完美。答案仍然相关。+ 1 – joshmcode 2016-11-02 21:22:25