如何在测试类中重写Program.cs禁用ASP.NET Core Razor Pages的身份验证与授权?
问题描述
我的集成测试类执行失败,报错:
System.Net.Http.HttpRequestException : Response status code does not indicate success: 302 (Found).
手动注释掉Program.cs(.NET 6)中的身份验证与授权代码后,测试就能正常运行:
//builder.Services.AddRazorPages() // .AddRazorPagesOptions(options => { // options.Conventions.AuthorizeFolder("/"); // 给所有文件夹下的页面应用[Authorize]特性 // }) // .AddMicrosoftIdentityUI(); builder.Services.AddRazorPages();
怎么在下面的测试类里重写Program.cs的配置,禁用ASP.NET Core Razor Pages应用的身份验证与授权?
public class IntegrationTests : IClassFixture<WebApplicationFactory<Program>> { private readonly WebApplicationFactory<Program> _factory; public IntegrationTests(WebApplicationFactory<Program> factory) { _factory = factory.WithWebHostBuilder(builder => { // 为测试重写服务配置 builder.ConfigureServices(services => { // 移除Razor Pages的授权策略 services.AddRazorPages(); }); }); } [Theory] [InlineData("/")] public async Task Get_EndpointsReturnSecurePageAsync(string url) { // 准备 var client = _factory.CreateClient(); // 执行 var response = await client.GetAsync(url); // 断言 response.EnsureSuccessStatusCode(); // 状态码200-299 Assert.Equal("text/html; charset=utf-8", response.Content.Headers.ContentType.ToString()); } }
解决方案
要在集成测试中禁用身份验证和授权,需要在WithWebHostBuilder的ConfigureServices里做以下操作:
- 清除已注册的Razor Pages相关服务,确保新配置能覆盖原有设置
- 重新注册不带全局授权的Razor Pages
- 添加一个测试用的空身份验证处理器,避免请求被重定向到登录页
修改后的测试类代码如下:
public class IntegrationTests : IClassFixture<WebApplicationFactory<Program>> { private readonly WebApplicationFactory<Program> _factory; public IntegrationTests(WebApplicationFactory<Program> factory) { _factory = factory.WithWebHostBuilder(builder => { builder.ConfigureServices(services => { // 清除已注册的Razor Pages服务 var razorPagesDescriptor = services.SingleOrDefault( d => d.ServiceType == typeof(IRazorPagesMvcBuilder)); if (razorPagesDescriptor != null) { services.Remove(razorPagesDescriptor); } // 重新注册Razor Pages,清除所有全局授权约定 services.AddRazorPages(options => { options.Conventions.AuthorizeFolder("/").Clear(); }); // 添加测试用的身份验证方案,让请求自动通过身份验证 services.AddAuthentication("TestAuth") .AddScheme<AuthenticationSchemeOptions, TestAuthenticationHandler>( "TestAuth", options => { }); }); }); } [Theory] [InlineData("/")] public async Task Get_EndpointsReturnSecurePageAsync(string url) { var client = _factory.CreateClient(); var response = await client.GetAsync(url); response.EnsureSuccessStatusCode(); Assert.Equal("text/html; charset=utf-8", response.Content.Headers.ContentType.ToString()); } } // 测试用的空身份验证处理器,返回已通过验证的身份 public class TestAuthenticationHandler : AuthenticationHandler<AuthenticationSchemeOptions> { public TestAuthenticationHandler( IOptionsMonitor<AuthenticationSchemeOptions> options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) { } protected override Task<AuthenticateResult> HandleAuthenticateAsync() { // 构造一个模拟的已验证身份 var claims = new[] { new Claim(ClaimTypes.Name, "TestUser") }; var identity = new ClaimsIdentity(claims, Scheme.Name); var principal = new ClaimsPrincipal(identity); var ticket = new AuthenticationTicket(principal, Scheme.Name); return Task.FromResult(AuthenticateResult.Success(ticket)); } }
关键要点
- 清除原有
IRazorPagesMvcBuilder服务是为了避免原有带授权的配置生效 options.Conventions.AuthorizeFolder("/").Clear()直接移除了全局的文件夹授权约定- 测试用身份验证处理器会自动让所有请求通过身份验证,不会触发302重定向
- 如果你的应用中间件管道里有强制的授权检查,还可以在
Configure方法里调整管道,比如跳过UseAuthorization()中间件
内容的提问来源于stack exchange,提问作者Steve
相关产品推荐
相关产品推荐

