我已经为Web API编写了一个 Action 过滤器。如果api Controller 中的方法抛出未处理的异常,则过滤器将创建内部错误500响应。

我需要知道如何测试过滤器?

我已经进行了广泛的研究,但无法创建合适的测试。我尝试了上下文模拟,服务定位器实现,甚至使用测试服务器进行集成测试。

Web API Controller 如下所示:

namespace Plod.Api.ApiControllers
{
    [TypeFilter(typeof(UnhandledErrorFilterAttribute))]
    [Route("api/[controller]")]
    public class GamesController : BaseApiController
    {
        public GamesController(IGameService repository,
            ILogger<GamesController> logger,
            IGameFactory gameFactory
            ) : base(
                repository,
                logger,
                gameFactory
                )
        { }

        // ..... controller methods are here
    }
}

完整的 Controller 位于here

过滤器是这样的:
namespace Plod.Api.Filters
{
    public class UnhandledErrorFilterAttribute : ActionFilterAttribute
    {
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            if (filterContext.Exception != null)
            {
                filterContext.HttpContext.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
                filterContext.ExceptionHandled = true;
            }
        }
    }
}

我什至欢迎对过滤器实现进行更改,以解决此问题。任何帮助或想法将不胜感激。谢谢。

最佳答案

你可能做不到。但是,您可以做的是旋转 TestServer ,然后使用HttpClient对其进行设置。这确实是集成测试,而不是单元测试。但是,这是一种很好的集成测试,因为它可以在管道中安全运行。

本文档说明了如何执行此操作:
https://docs.microsoft.com/en-us/aspnet/core/test/integration-tests?view=aspnetcore-3.1

您将要面对的问题是,您将需要在应用程序内部模拟基础服务。如果不这样做,整个服务器将启动,并尝试访问数据库等。这是一个示例。这是使用最小起订量。顺便说一句,我与单元测试共享ConfigureServices方法,因此它们使用相同的模拟服务对象网格。您仍然可以使用Moq或NSubstitute的全部功能来测试后端(甚至前端)。

我可以在测试中使用断点击中我的属性。

private void ConfigureServices(IServiceCollection services)
{
    var hostBuilder = new WebHostBuilder();
    hostBuilder.UseStartup<TestStartup>();
    hostBuilder.ConfigureServices(services =>
    {
        ConfigureServices(services);
    });

    _testServer = new TestServer(hostBuilder);
    _httpClient = _testServer.CreateClient();
}


private void ConfigureServices(IServiceCollection services)
{
    services.AddSingleton(_storageManagerFactory.Object);
    services.AddSingleton(_blobReferenceManagerMock.Object);
    services.AddSingleton(_ipActivitiesLoggerMocker.Object);
    services.AddSingleton(_loggerFactoryMock.Object);
    services.AddSingleton(_hashingService);
    services.AddSingleton(_settingsServiceMock.Object);
    services.AddSingleton(_ipActivitiesManager.Object);
    services.AddSingleton(_restClientMock.Object);
    _serviceProvider = services.BuildServiceProvider();
}


public class TestStartup
{
    public void Configure(
        IApplicationBuilder app,
        ISettingsService settingsService)
    {
        app.Configure(settingsService.GetSettings());
    }

    public IServiceProvider ConfigureServices(IServiceCollection services)
    {
        var mvc = services.AddMvc(option => option.EnableEndpointRouting = false);
        mvc.AddApplicationPart(typeof(BlobController).Assembly);
        services.AddSingleton(new Mock<IHttpContextAccessor>().Object);
        return services.BuildServiceProvider();
    }
}

关于asp.net-core-mvc - 如何在asp.net核心中对Web api的 Action 过滤器属性进行单元测试?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/46576517/

10-17 02:32