ASP.Net Core 7.0 Angular SPA集成测试WebApplicationFactory返回404问题
问题:ASP.Net Core 7.0 + Angular SPA集成测试返回404,传统Web App正常
我正在搭建包含集成测试的ASP.Net Core 7.0 + Angular SPA应用,使用WebApplicationFactory执行集成测试时,所有请求均返回404状态码。但将相同测试配置应用于传统ASP.Net Core Web App时,能正常返回页面及200状态码。我清楚页面由客户端渲染,但至少期望服务器能返回内容,请问我遗漏了什么配置?
Angular应用代码
主项目Program.cs
public class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseSetting(WebHostDefaults.ApplicationKey, typeof(Startup).Assembly.GetName().Name); webBuilder.UseStartup<Startup>(); }); }
Startup.cs
public class Startup { private readonly IConfiguration _configuration; public Startup(IConfiguration configuration) { _configuration = configuration; } public virtual void ConfigureServices(IServiceCollection services) { services.AddControllersWithViews(); } public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env) { if (!env.IsDevelopment()) { // 默认HSTS有效期为30天,生产环境可按需调整 app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller}/{action=Index}/{id?}"); endpoints.MapFallbackToFile("index.html"); }); } }
集成测试项目HomeControllerTests.cs
public class HomeControllerTests: IClassFixture<WebApplicationFactory<Startup>> { private readonly WebApplicationFactory<Startup> _factory; public HomeControllerTests(WebApplicationFactory<Startup> factory) { _factory = factory; } [Theory] [InlineData("/")] [InlineData("/fetch-data")] public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url) { // Arrange using var client = _factory.CreateClient(); // Act using var response = await client.GetAsync(url); // Assert response.EnsureSuccessStatusCode(); Assert.Equal("text/html; charset=utf-8", response.Content.Headers.ContentType.ToString()); } }
传统Web应用代码
主项目Program.cs
public static class Program { public static void Main(string[] args) { CreateHostBuilder(args).Build().Run(); } public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args) .ConfigureWebHostDefaults(webBuilder => { webBuilder.UseSetting(WebHostDefaults.ApplicationKey, typeof(Startup).Assembly.GetName().Name); webBuilder.UseStartup<Startup>(); }); }
Startup.cs
public class Startup { private readonly IConfiguration _configuration; public Startup(IConfiguration configuration) { _configuration = configuration; } public virtual void ConfigureServices(IServiceCollection services) { // 向容器添加服务 services.AddRazorPages(); } public virtual void Configure(IApplicationBuilder app, IWebHostEnvironment env) { // 配置HTTP请求管道 if (!env.IsDevelopment()) { app.UseExceptionHandler("/Error"); // 默认HSTS有效期为30天,生产环境可按需调整 app.UseHsts(); } app.UseHttpsRedirection(); app.UseStaticFiles(); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapRazorPages(); }); } }
集成测试项目HomeControllerTests.cs
public class HomeControllerTests: IClassFixture<WebApplicationFactory<Startup>> { private readonly WebApplicationFactory<Startup> _factory; public HomeControllerTests(WebApplicationFactory<Startup> factory) { _factory = factory; } [Theory] [InlineData("/")] [InlineData("/Privacy")] public async Task Get_EndpointsReturnSuccessAndCorrectContentType(string url) { // Arrange using var client = _factory.CreateClient(); // Act using var response = await client.GetAsync(url); // Assert response.EnsureSuccessStatusCode(); Assert.Equal("text/html; charset=utf-8", response.Content.Headers.ContentType.ToString()); } }
解决方案
核心原因是:Angular SPA的静态文件(比如index.html)需要通过ng build编译生成,默认不会被WebApplicationFactory在测试环境中自动加载;而传统Web App的Razor Pages文件属于项目编译资源,测试时会被自动包含。
1. 确保静态文件可被测试环境访问
- 先构建Angular项目:运行
ng build命令生成编译后的静态文件(默认在ClientApp/dist目录,根据你的项目结构调整路径)。 - 配置静态文件路径:修改Startup.cs中的
UseStaticFiles,指定Angular编译后的文件目录:app.UseStaticFiles(new StaticFileOptions { FileProvider = new PhysicalFileProvider( Path.Combine(env.ContentRootPath, "ClientApp/dist")), // 替换为你的Angular dist实际路径 RequestPath = "" }); - 调整测试项目的内容根目录:自定义WebApplicationFactory,让测试环境指向主项目目录,确保能找到静态文件:
然后测试类继承这个自定义工厂:public class CustomWebApplicationFactory<TStartup> : WebApplicationFactory<TStartup> where TStartup : class { protected override void ConfigureWebHost(IWebHostBuilder builder) { // 替换为你的ASP.Net Core主项目相对路径 var mainProjectPath = Path.Combine(Directory.GetCurrentDirectory(), "../YourAspNetCoreProject"); builder.UseContentRoot(mainProjectPath); base.ConfigureWebHost(builder); } }public class HomeControllerTests: IClassFixture<CustomWebApplicationFactory<Startup>> { // 其余代码保持不变 }
2. 验证Fallback路由有效性
你已经配置了endpoints.MapFallbackToFile("index.html");,这是SPA必备的路由回退规则,但要确保index.html确实存在于你配置的静态文件目录中。
3. 避免测试环境禁用静态文件
检查代码中是否有条件性禁用UseStaticFiles的逻辑(比如只在开发环境启用),确保测试环境下静态文件中间件正常工作。
可选:自动构建Angular(无需手动执行ng build)
可以在测试项目的构建事件中添加命令,自动触发Angular构建:
cd "$(SolutionDir)ClientApp" ng build --configuration production
这样每次运行测试前都会自动构建Angular,确保静态文件是最新的。
内容的提问来源于stack exchange,提问作者DeLoooping
相关产品推荐
相关产品推荐

