这可能只是一种需要另一双眼睛的情况。我一定是漏掉了什么,但是我不明白为什么这种东西不能被测试。我基本上是想确保未经身份验证的用户无法访问视图,方法是将控制器标记为Authorize属性,并尝试使用以下代码对此进行测试:
[Fact]
public void ShouldRedirectToLoginForUnauthenticatedUsers()
{
var mockControllerContext = new Mock<ControllerContext>()
{ DefaultValue = DefaultValue.Mock };
var controller = new MyAdminController()
{ControllerContext = mockControllerContext.Object};
mockControllerContext.Setup(c =>
c.HttpContext.Request.IsAuthenticated).Returns(false);
var result = controller.Index();
Assert.IsAssignableFrom<RedirectResult>(result);
}
我正在寻找的索引是某种类型的指示,表明用户正被重定向到登录表单,但是总是返回一个ViewResult,并且在调试时我可以看到,即使用户没有经过身份验证,也成功地命中了RedirectResult ()方法。
我做错了什么吗?在错误的级别进行测试?我是不是应该在路由级别测试这类东西?
我知道Authorize属性是有效的,因为当我打开页面时,登录屏幕确实是强加给我的--但是我如何在测试中验证这一点呢?
控制器和索引方法非常简单,这样我就可以验证行为。为了完整起见,我将它们包括在内:
[Authorize]
public class MyAdminController : Controller
{
public ActionResult Index()
{
return View();
}
}
感谢任何帮助..。
发布于 2011-03-10 11:48:36
你可能在错误的级别上进行测试,但是这个测试是有意义的。我的意思是,如果我用authorize(Roles=“超级英雄”)属性标记一个方法,如果我标记了它,我真的不需要测试。我想要的是测试一个未经授权的用户是否没有访问权限,而一个授权用户是否有访问权限。
对于未经授权的用户,执行如下测试:
// Arrange
var user = SetupUser(isAuthenticated, roles);
var controller = SetupController(user);
// Act
SomeHelper.Invoke(controller => controller.MyAction());
// Assert
Assert.AreEqual(401,
controller.ControllerContext.HttpContext.Response.StatusCode, "Status Code");
嗯,这并不容易,我花了10个小时,但这就是它。我希望有人能从中受益,或者说服我从事另一种职业。:) (BTW -我使用的是rhino mock)
[Test]
public void AuthenticatedNotIsUserRole_Should_RedirectToLogin()
{
// Arrange
var mocks = new MockRepository();
var controller = new FriendsController();
var httpContext = FakeHttpContext(mocks, true);
controller.ControllerContext = new ControllerContext
{
Controller = controller,
RequestContext = new RequestContext(httpContext, new RouteData())
};
httpContext.User.Expect(u => u.IsInRole("User")).Return(false);
mocks.ReplayAll();
// Act
var result =
controller.ActionInvoker.InvokeAction(controller.ControllerContext, "Index");
var statusCode = httpContext.Response.StatusCode;
// Assert
Assert.IsTrue(result, "Invoker Result");
Assert.AreEqual(401, statusCode, "Status Code");
mocks.VerifyAll();
}
不过,如果没有这个辅助函数,这就不是很有用了:
public static HttpContextBase FakeHttpContext(MockRepository mocks, bool isAuthenticated)
{
var context = mocks.StrictMock<HttpContextBase>();
var request = mocks.StrictMock<HttpRequestBase>();
var response = mocks.StrictMock<HttpResponseBase>();
var session = mocks.StrictMock<HttpSessionStateBase>();
var server = mocks.StrictMock<HttpServerUtilityBase>();
var cachePolicy = mocks.Stub<HttpCachePolicyBase>();
var user = mocks.StrictMock<IPrincipal>();
var identity = mocks.StrictMock<IIdentity>();
var itemDictionary = new Dictionary<object, object>();
identity.Expect(id => id.IsAuthenticated).Return(isAuthenticated);
user.Expect(u => u.Identity).Return(identity).Repeat.Any();
context.Expect(c => c.User).PropertyBehavior();
context.User = user;
context.Expect(ctx => ctx.Items).Return(itemDictionary).Repeat.Any();
context.Expect(ctx => ctx.Request).Return(request).Repeat.Any();
context.Expect(ctx => ctx.Response).Return(response).Repeat.Any();
context.Expect(ctx => ctx.Session).Return(session).Repeat.Any();
context.Expect(ctx => ctx.Server).Return(server).Repeat.Any();
response.Expect(r => r.Cache).Return(cachePolicy).Repeat.Any();
response.Expect(r => r.StatusCode).PropertyBehavior();
return context;
}
因此,这将使您确认不属于某个角色的用户没有访问权限。我试着写一个测试来确认相反的情况,但在花了两个多小时深入研究mvc管道之后,我将把它留给手动测试人员。(当我到达VirtualPathProviderViewEngine课程时,我放弃了。见鬼?我不想要任何东西去做VirtualPath、Provider或ViewEngine,而是三者的结合!)
我很好奇为什么这在一个所谓的“可测试”框架中是如此困难。
发布于 2009-04-12 11:08:11
为什么不使用反射来查找控制器类和/或正在测试的操作方法上的[Authorize]
属性呢?假设框架确实确保了该属性得到遵守,这将是最容易做的事情。
发布于 2021-02-24 04:31:57
对于.NET框架,我们使用这个类来验证每个MVC和API Controller都有AuthorizeAttribute
,并且每个API Controller都应该有一个RoutePrefixAttribute
。
[TestFixture]
public class TestControllerHasAuthorizeRole
{
private static IEnumerable<Type> GetChildTypes<T>()
{
var types = typeof(Startup).Assembly.GetTypes();
return types.Where(t => t.IsSubclassOf(typeof(T)) && !t.IsAbstract);
}
[Test]
public void MvcControllersShouldHaveAuthrorizeAttribute()
{
var controllers = GetChildTypes<Controller>();
foreach (var controller in controllers)
{
var authorizeAttribute = Attribute.GetCustomAttribute(controller, typeof(System.Web.Mvc.AuthorizeAttribute), true) as System.Web.Mvc.AuthorizeAttribute;
Assert.IsNotNull(authorizeAttribute, $"MVC-controller {controller.FullName} does not implement AuthorizeAttribute");
}
}
[Test]
public void ApiControllersShouldHaveAuthorizeAttribute()
{
var controllers = GetChildTypes<ApiController>();
foreach (var controller in controllers)
{
var attribute = Attribute.GetCustomAttribute(controller, typeof(System.Web.Http.AuthorizeAttribute), true) as System.Web.Http.AuthorizeAttribute;
Assert.IsNotNull(attribute, $"API-controller {controller.FullName} does not implement AuthorizeAttribute");
}
}
[Test]
public void ApiControllersShouldHaveRoutePrefixAttribute()
{
var controllers = GetChildTypes<ApiController>();
foreach (var controller in controllers)
{
var attribute = Attribute.GetCustomAttribute(controller, typeof(System.Web.Http.RoutePrefixAttribute), true) as System.Web.Http.RoutePrefixAttribute;
Assert.IsNotNull(attribute, $"API-controller {controller.FullName} does not implement RoutePrefixAttribute");
Assert.IsTrue(attribute.Prefix.StartsWith("api/", StringComparison.OrdinalIgnoreCase), $"API-controller {controller.FullName} does not have a route prefix that starts with api/");
}
}
}
在.NET核心和.NET 5<中,这要容易一些。在这里,MVC Controller继承自Controller
,而后者又继承自ControllerBase
。Api控制器直接继承自ControllerBase
,因此我们可以使用单一的方法测试MVC和API控制器:
public class AuthorizeAttributeTest
{
private static IEnumerable<Type> GetChildTypes<T>()
{
var types = typeof(Startup).Assembly.GetTypes();
return types.Where(t => t.IsSubclassOf(typeof(T)) && !t.IsAbstract);
}
[Fact]
public void ApiAndMVCControllersShouldHaveAuthorizeAttribute()
{
var controllers = GetChildTypes<ControllerBase>();
foreach (var controller in controllers)
{
var attribute = Attribute.GetCustomAttribute(controller, typeof(Microsoft.AspNetCore.Authorization.AuthorizeAttribute), true) as Microsoft.AspNetCore.Authorization.AuthorizeAttribute;
Assert.NotNull(attribute);
}
}
}
https://stackoverflow.com/questions/669175
复制相似问题