我有一个使用ASP.NET Core MVC的API,其中控制器需要进行单元测试。
控制器:
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System.Threading.Tasks;
namespace TransitApi.Api.Controllers
{
[Route("api/foo")]
public class FooController : Controller
{
private IFooRepository FooRepository { get; }
public FooController(IFooRepository fooRepository)
{
FooRepository = fooRepository;
}
[HttpGet]
[Authorize("scopes:getfoos")]
public async Task<IActionResult> GetAsync()
{
var foos = await FooRepository.GetAsync();
return Json(foos);
}
}
}
我必须能够对AuthorizeAttribute
的有效性进行单元测试是至关重要的。我们的代码库中存在属性缺失和错误范围的问题。虽然这个答案正是我所需要的,但由于Microsoft.AspNetCore.Mvc.Controller
中没有ActionInvoker
方法,因此我无法采用这种方式。
单元测试:
[Fact]
public void GetAsync_InvalidScope_ReturnsUnauthorizedResult()
{
// Arrange
var fooRepository = new StubFooRepository();
var controller = new FooController(fooRepository)
{
ControllerContext = new ControllerContext
{
HttpContext = new FakeHttpContext()
// User unfortunately not available in HttpContext
//,User = new User() { Scopes = "none" }
}
};
// Act
var result = controller.GetAsync().Result;
// Assert
Assert.IsType<UnauthorizedResult>(result);
}
如何对我的控制器方法进行单元测试,以验证没有正确权限的用户被拒绝访问?
目前我只测试了AuthorizeAttribute
的存在,但这样做远远不够:
[Fact]
public void GetAsync_Analysis_HasAuthorizeAttribute()
{
// Arrange
var fooRepository = new StubFooRepository();
var controller = new FooController(fooRepository)
{
ControllerContext = new ControllerContext
{
HttpContext = new FakeHttpContext()
}
};
// Act
var type = controller.GetType();
var methodInfo = type.GetMethod("GetAsync", new Type[] { });
var attributes = methodInfo.GetCustomAttributes(typeof(AuthorizeAttribute), true);
// Assert
Assert.True(attributes.Any());
}
AuthorizeAttribute
是否存在还不够?AuthorizeAttribute
既是属性也是一个IAuthorizationFilter
,属性部分并不能执行任何操作,它只是元数据。MVC的单元测试保证了如果有此属性,则将其注册为当前请求的授权过滤器并运行逻辑。如果您使用AuthorizeAttribute
的子类,那么测试其逻辑是有意义的,但是由于您没有使用子类,因此您需要检查的唯一内容是属性的存在以及其属性(用户
和组
)的配置。 - NightOwl888AuthorizeAttribute
,然后使用AllowAnonymous
来覆盖行为。这样,它们默认是被锁定的,您就不必担心稍后更改会遗漏一个。或者,您可以创建自己的自定义IAuthorizationFilter
全局注册,管理整个应用程序的安全性(甚至可能是您自己的属性来执行某些操作),这可以作为与控制器和操作分开测试的单独部分。 - NightOwl888