在 ASP.NET Core MVC API 控制器上对 AuthorizeAttribute 进行单元测试 [英] Unit testing an AuthorizeAttribute on an ASP.NET Core MVC API controller

查看:21
本文介绍了在 ASP.NET Core MVC API 控制器上对 AuthorizeAttribute 进行单元测试的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有需要进行单元测试的控制器的 ASP.NET Core MVC API.

I have a ASP.NET Core MVC API with controllers that need to be unit tested.

控制器:

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 中没有 ActionInvoker 方法.AspNetCore.Mvc.Controller 意味着我不能这样做.

It is essential that I am able to unit test the effectiveness of the AuthorizeAttribute. We have had issues in our code base with missing attributes and incorrect scopes. This answer is exactly what I am looking for, but not having a ActionInvoker method in Microsoft.AspNetCore.Mvc.Controller means I am not able to do it this way.

单元测试:

[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 的存在,如下所示,但这确实不够好:

Currently I have settled for testing merely the presence of an AuthorizeAttribute as follows, but this is really not good enough:

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

推荐答案

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

This would need integration testing with an in-memory test server because the attribute is evaluated by the framework as it processes the request pipeline.

ASP.NET Core 中的集成测试

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

Integration testing ensures that an application's components function correctly when assembled together. ASP.NET Core supports integration testing using unit test frameworks and a built-in test web host that can be used to handle requests without network overhead.

[Fact]
public async Task GetAsync_InvalidScope_ReturnsUnauthorizedResult() {
    // Arrange
    var server = new TestServer(new WebHostBuilder().UseStartup<Startup>());
    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 的任何依赖项.

You can also create a start up specifically for the test that will replace any dependencies for DI with stubs/mocks if you do not want the test hitting actual production implementations.

这篇关于在 ASP.NET Core MVC API 控制器上对 AuthorizeAttribute 进行单元测试的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆