集成测试调用接口出现500错误:SQLite无Categories表问题排查
问题分析与解决方案
你的测试报错核心原因是:测试环境中的SQLite数据库未创建Categories表。主项目运行正常是因为你已经初始化过数据库结构,但测试启动时并没有自动复用这个已初始化的数据库(或未正确初始化测试用数据库)。
以下是具体的修复步骤:
1. 自定义测试用WebApplicationFactory
通过重写WebApplicationFactory,我们可以控制测试环境的服务配置,确保测试数据库被正确初始化:
public class CustomWebApplicationFactory : WebApplicationFactory<Program> { protected override void ConfigureWebHost(IWebHostBuilder builder) { builder.ConfigureServices(services => { // 移除原有DataContext的注册 var dbDescriptor = services.SingleOrDefault( d => d.ServiceType == typeof(DbContextOptions<DataContext>)); if (dbDescriptor != null) { services.Remove(dbDescriptor); } // 注册测试用SQLite数据库(可选择内存版或独立文件) services.AddDbContext<DataContext>(options => { // 内存版SQLite,测试结束自动销毁,适合隔离测试 options.UseSqlite("Data Source=:memory:"); // 若要使用文件数据库,替换为:options.UseSqlite("Data Source=test_api.db"); }); // 初始化数据库结构 var serviceProvider = services.BuildServiceProvider(); using var scope = serviceProvider.CreateScope(); var scopedServices = scope.ServiceProvider; var dbContext = scopedServices.GetRequiredService<DataContext>(); // 自动创建所有表(基于实体模型) dbContext.Database.EnsureCreated(); // 可选:添加测试种子数据 // dbContext.Categories.Add(new Category { Name = "Test Category" }); // dbContext.SaveChanges(); }); } }
2. 修改测试类使用自定义工厂
让测试类依赖自定义的工厂,确保每次测试都使用正确初始化的数据库:
public class CategoryContollerTests : IClassFixture<CustomWebApplicationFactory> { private readonly WebApplicationFactory<Program> _factory; public CategoryContollerTests(CustomWebApplicationFactory factory) { _factory = factory; } [Fact] public async Task Get_ReturnCategory() { var client = _factory.CreateClient(); var response = await client.GetAsync("api/Categories"); // 添加断言验证响应状态 response.EnsureSuccessStatusCode(); } }
关键注意事项
- 隔离测试数据:使用内存SQLite或独立测试文件数据库,避免测试污染主项目的数据库数据。
- 初始化时机:通过
EnsureCreated()可以快速基于实体模型创建表,若使用EF迁移,也可替换为dbContext.Database.Migrate()来执行迁移脚本。 - 配置一致性:若坚持复用主项目数据库,需确保测试项目的
appsettings.json中DefaultConnection连接字符串与主项目完全一致,且测试启动前数据库已存在表结构。
内容的提问来源于stack exchange,提问作者Palamar66
相关产品推荐
相关产品推荐

