在ASP.NET Core MVC API控制器上对AuthorizeAttribute进行unit testing

我有一个ASP.NET核心MVC API与控制器需要进行unit testing。

控制器:

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 GetAsync() { var foos = await FooRepository.GetAsync(); return Json(foos); } } } 

我必须能够对AuthorizeAttribute的有效性进行unit testing。 我们的代码库中存在缺少属性和不正确范围的问题。 这个答案正是我正在寻找的,但在Microsoft.AspNetCore.Mvc.Controller没有ActionInvoker方法意味着我无法这样做。

unit testing:

 [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(result); } 

如何对没有正确范围的用户进行unit testing,拒绝访问我的控制器方法?

目前我已经决定只测试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()); } 

这需要与内存中测试服务器进行集成测试,因为该属性在框架处理请求管道时由框架进行评估。

ASP.NET Core中的集成测试

集成测试可确保应用程序组件在组装在一起时正常运行。 ASP.NET Core支持使用unit testing框架和内置测试Web主机进行集成测试,可用于处理请求而无需网络开销。

 [Fact] public async Task GetAsync_InvalidScope_ReturnsUnauthorizedResult() { // Arrange var server = new TestServer(new WebHostBuilder().UseStartup()); var client = server.CreateClient(); var url = "api/foo"; var expected = HttpStatusCode.Unauthorized; // Act var response = await client.GetAsync(url); // Assert Assert.AreEqual(expected, response.StatusCode); } 

如果您不希望测试达到实际的生产实现,您还可以专门为测试创建一个启动,以替换存根/模拟的DI的任何依赖项。