gpt4 book ai didi

c# - 集成测试中的 MVC 策略覆盖

转载 作者:太空宇宙 更新时间:2023-11-03 12:02:41 25 4
gpt4 key购买 nike

我正在为一个 MVC 应用程序添加集成测试。我们的许多端点都应用了策略,例如

namespace WorkProject
{
[Route("A/Route")]
public class WorkController : Controller
{
[HttpPost("DoStuff")]
[Authorize(Policy = "CanDoStuff")]
public IActionResult DoStuff(){/* */}
}
}

对于我们的集成测试,我已经覆盖了 WebApplicationFactory,就像 ASP .NET Core documentation 中建议的那样.我的目标是通过创建一个允许所有各方通过授权策略的类来重载身份验证步骤并绕过该策略。

namespace WorkApp.Tests
{
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup: class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
base.ConfigureWebHost(builder);
builder.ConfigureServices(services =>
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Test Scheme"; // has to match scheme in TestAuthenticationExtensions
options.DefaultChallengeScheme = "Test Scheme";
}).AddTestAuth(o => { });


services.AddAuthorization(options =>
{
options.AddPolicy("CanDoStuff", policy =>
policy.Requirements.Add(new CanDoStuffRequirement()));
});

// I've also tried the line below, but neither worked
// I figured that maybe the services in Startup were added before these
// and that a replacement was necessary
// services.AddTransient<IAuthorizationHandler, CanDoStuffActionHandler>();
services.Replace(ServiceDescriptor.Transient<IAuthorizationHandler, CanDoStuffActionHandler>());
});
}
}

internal class CanDoStuffActionHandler : AuthorizationHandler<CanDoStuffActionRequirement>
{
public CanDoStuffActionHandler()
{
}

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CanDoStuffActionRequirement requirement)
{
context.Succeed(requirement);

return Task.CompletedTask;
}
}

internal class CanDoStuffRequirement : IAuthorizationRequirement
{
}
}

我对服务做的第一件事是按照建议覆盖身份验证 here (没有关于覆盖 Startup 的内容,因为这对我来说似乎不起作用)。我倾向于相信这种身份验证覆盖有效。当我运行我的测试时,我从 xUnit 测试框架内收到一个 HTTP 403。如果我从 PostMan 访问我正在测试的路由,我会收到 HTTP 401。我还在自定义 Web 应用程序工厂中创建了一个类,该类允许对 CanDoStuff 授权处理程序的所有请求。我认为这将允许通过授权策略进行集成测试,但是,如上所述,我收到 HTTP 403。我知道如果应用程序不知道某些文件在哪里,将返回 403。然而,这是一个严格用于接收和处理数据的 post 路由,并且该路由不会尝试返回任何 View ,因此这个 403 很可能与授权策略有关,由于某种原因,授权策略没有被覆盖。

我显然做错了什么。当我在 Debug模式下运行测试并在 HandleRequirementsAsync 函数中设置断点时,应用程序永远不会中断。有没有其他方法可以让我尝试覆盖授权策略?

最佳答案

这是我做的。

  1. 覆盖WebApplicationFactory和我自己的。注意,我仍然添加了我的应用程序的启 Action 为模板参数
  2. 创建我的启动函数 overrides the ConfigureAuthServices我添加的功能。
  3. ConfigureWebHost 函数中告诉构建器使用我的自定义启动类。
  4. 通过 builder.ConfigureServices 覆盖 ConfigureWebHost 函数中的身份验证步骤。
  5. ConfigureWebHost 函数中的 builder.ConfigureServices 末尾添加对 Controller 的程序集引用,我试图访问其端点。
  6. 为允许所有请求成功的策略编写我自己的 IAuthorizationHandler

我希望我已经很好地解释了我所做的事情。如果没有,希望下面的示例代码足够简单易懂。

你的 Controller .cs

namespace YourApplication
{
[Route("A/Route")]
public class WorkController : Controller
{
[HttpPost("DoStuff")]
[Authorize(Policy = "CanDoStuff")]
public IActionResult DoStuff(){/* */}
}
}

测试.cs

namespace YourApplication.Tests
{
public class Tests
: IClassFixture<CustomWebApplicationFactory<YourApplication.Startup>>
{
private readonly CustomWebApplicationFactory<YourApplication.Startup> _factory;

public Tests(CustomWebApplicationFactory<YourApplication.Startup> factory)
{
_factory = factory;
}

[Fact]
public async Task SomeTest()
{
var client = _factory.CreateClient();
var response = await client.PostAsync("/YourEndpoint");
response.EnsureSuccessStatusCode();

Assert.Equal(/* whatever your condition is */);
}
}
}

CustomWebApplicationFactory.cs

namespace YourApplication.Tests
{
public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup: class
{
protected override void ConfigureWebHost(IWebHostBuilder builder)
{
base.ConfigureWebHost(builder);
builder.ConfigureServices(services =>
{
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = "Test Scheme"; // has to match scheme in TestAuthenticationExtensions
options.DefaultChallengeScheme = "Test Scheme";
}).AddTestAuth(o => { });


services.AddAuthorization(options =>
{
options.AddPolicy("CanDoStuff", policy =>
policy.Requirements.Add(new CanDoStuffRequirement()));
});

services.AddMvc().AddApplicationPart(typeof(YourApplication.Controllers.YourController).Assembly);
services.AddTransient<IAuthorizationHandler, CanDoStuffActionHandler>();
});
builder.UseStartup<TestStartup>();
}
}

internal class CanDoStuffActionHandler : AuthorizationHandler<CanDoStuffActionRequirement>
{
public CanDoStuffActionHandler()
{
}

protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, CanDoStuffActionRequirement requirement)
{
context.Succeed(requirement);

return Task.CompletedTask;
}
}

internal class CanDoStuffRequirement : IAuthorizationRequirement
{
}
}

TestStartup.cs

namespace YourApplication.Tests
{
public class TestStartup : YourApplication.Startup
{
public TestStartup(IConfiguration configuration) : base(configuration)
{

}

protected override void ConfigureAuthServices(IServiceCollection services)
{
}
}
}

关于c# - 集成测试中的 MVC 策略覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56379327/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com