Я нахожусь в процессе добавления интеграционных тестов на работе для приложения MVC. К многим нашим конечным точкам применяются политики, например,
namespace WorkProject
{
[Route("A/Route")]
public class WorkController : Controller
{
[HttpPost("DoStuff")]
[Authorize(Policy = "CanDoStuff")]
public IActionResult DoStuff(){/* */}
}
}
Для наших интеграционных тестов я переопределил WebApplicationFactory
, как это предлагается в документации ASP .NET Core . Моя цель состояла в том, чтобы перегрузить этап аутентификации и обойти политику, создав класс, который позволяет всем сторонам проходить политику авторизации.
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
{
}
}
Первое, что я делаю со службами, это переопределение аутентификации, как предложено здесь (без бит о переопределении Startup
, так как это, похоже, не работает для меня). Я склонен полагать, что это переопределение аутентификации работает. Когда я запускаю свои тесты, я получаю HTTP 403 из среды тестирования xUnit. Если я попадаю на маршрут, который я тестирую из PostMan, я получаю HTTP 401. Я также создал класс, который живет в фабрике пользовательских веб-приложений, которая разрешает все запросы для обработчика авторизации CanDoStuff
. Я думал, что это позволит провести интеграционные тесты с помощью политики авторизации, но, как указано выше, я получаю HTTP 403. Я знаю, что 403 будет возвращено, если приложение не знает, где находятся определенные файлы. Однако это пост-маршрут, предназначенный исключительно для получения и обработки данных, и этот маршрут не пытается вернуть какие-либо представления, поэтому этот 403, скорее всего, связан с политикой авторизации, которая по какой-то причине не переопределяется.
Я явно что-то делаю не так. Когда я запускаю тест в режиме отладки и устанавливаю точку останова в функции HandleRequirementsAsync
, приложение никогда не прерывается. Есть ли другой способ, которым я должен пытаться переопределить политики авторизации?