是否有任何建议的方法来单独测试一个MVC控制器方法的安全性(在ASP.NET MVC 5中)?例如我有管理员用户和普通用户,我希望进行单元测试,以确保只有管理员才能访问某些页面。 e.g:
/// <summary>
/// Initial page for creating a new <see cref="Widget"/>.
/// </summary>
/// <returns>
/// An <see cref="ActionResult"/> used to indicate the view to be
/// rendered. Guaranteed not to be null or empty.
/// </returns>
[HttpGet]
[Authorize(Roles = "ADMIN")]
public ActionResult Create()
{
return this.View(new CreateWidgetModel());
}
......单元测试应该是这样的:
using (var userStore = new MyUserStore())
{
using (var userManager = new MyUserManager(userStore))
{
if (await userManager.HasAdministratorUserAsync())
{
await userStore.DeleteAsync(await userManager.FindByNameAsync(MyUserManager.AdministratorUserName));
}
ApplicationUser adminUser = await userManager.CreateAdministratorUserAsync();
ClaimsIdentity claimsIdentity = await userManager.CreateIdentityAsync(adminUser, "Forms");
this.MockHttpContext.SetupGet(x => x.User).Returns(new GenericPrincipal(claimsIdentity, adminUser.Roles.ToArray()));
List<MethodInfo> methodInfos = this.Sut.GetType().GetMethods().Where(m => m.Name == "Create" && typeof(ActionResult).IsAssignableFrom(m.ReturnType)).ToList();
Assert.AreEqual(2, methodInfos.Count, "Unexpected number of create methods");
foreach (var method in methodInfos)
{
Assert.IsTrue(method.IsDefined(typeof(ClaimsAuthorizeAttribute)), "No ClaimsAuthorize attribute was placed on the method");
ClaimsAuthorizeAttribute attribute = method.GetCustomAttribute<ClaimsAuthorizeAttribute>();
Assert.AreEqual(1, attribute.Claims.Length, "Unexpected number of claims");
AuthorizationContext authorizationContext = new AuthorizationContext(this.Sut.ControllerContext, new ReflectedActionDescriptor(method, "Create", new ReflectedControllerDescriptor(this.Sut.GetType())));
attribute.OnAuthorization(authorizationContext);
Assert.IsNotNull(authorizationContext.Result, "The authorization context result must not be null");
}
}
}
我现在遇到的问题是attribute.OnAuthorization
失败,出现以下空引用异常:
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.Mvc.OutputCacheAttribute.GetChildActionFilterFinishCallback(ControllerContext controllerContext)
at System.Web.Mvc.OutputCacheAttribute.IsChildActionCacheActive(ControllerContext controllerContext)
at System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext)
编辑:看到this post后,我现在得到了一个不同的空引用异常:
System.NullReferenceException: Object reference not set to an instance of an object.
at System.Web.Mvc.AuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext)
at MyProject.Support.Security.ClaimsAuthorizeAttribute.OnAuthorization(AuthorizationContext filterContext) in ClaimsAuthorizeAttribute.cs: line 106
编辑:看到OnAuthorization
here的源代码后,将其添加到我的测试中解决了我的问题:
this.MockHttpResponse.Setup(x => x.Cache).Returns(new Mock<HttpCachePolicyBase>().Object);
答案 0 :(得分:0)
您可以使用反射:
using System.Reflection;
var isAdmin = typeof(Controller).GetMethods().First(x => x.Name == "Create").GetCustomAttribute<Authorize>(false).Roles == "ADMIN";
基本思路是从方法中获取属性并检查角色。
答案 1 :(得分:0)
最简单的方法是使用Xania.AspNet.Simulator 1.2.3-beta(或更高版本)然后您可以编写如下测试:
using NUnit.Framework;
using Xania.AspNet.Simulator;
[TestCase("ADMIN", true)]
[TestCase("CUSTOMER", false)]
public void AdminRoleAuthorizationTest(string roleName, bool isAuthorized)
{
// arrange
var action = new AdminController().Action(c => c.Index()).Authenticate("user1", new[] {roleName});
// assert
Assert.AreEqual(isAuthorized, action.Authorize() == null);
}
有关更多示例,请参阅github上的测试项目