You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

集成测试项目多数据库配置异常:SQLite提示表不存在

问题解决方案

问题根源

你遇到的SQLite Error 1: 'no such table'错误,核心原因是:

  • 原MyDbContext的构造逻辑没有兼容测试环境的DI注入方式,导致它没有使用共享的内存连接,可能创建了独立的新内存数据库(无表结构);
  • 两个DbContext的表创建时机或作用域不匹配,导致某一方的表未被初始化到共享数据库中。

同时要注意SQLite内存库的特性:同一个连接对应同一个内存数据库,连接关闭后数据库立即销毁,你已保持连接打开的操作是正确的。


具体修复步骤

1. 修正MyDbContext构造函数

确保它同时支持生产环境的自定义构造和测试环境的DI注入:

public class MyDbContext : DbContext
{
    // 生产环境使用:通过工厂传入连接字符串和Schema
    public MyDbContext(DbContextOptions<MyDbContext> options, string connectionString, string schemaName)
        : base(options)
    {
        ModelBuilder.HasDefaultSchema(schemaName);
        // 可在此处补充连接字符串的自定义逻辑
    }

    // 测试环境使用:直接接受DI注入的配置
    public MyDbContext(DbContextOptions<MyDbContext> options) : base(options)
    {
    }

    // 你的DbSet定义和模型配置...
}

2. 重构测试用AddSqlite扩展方法

确保两个DbContext都正确绑定到共享的内存连接:

internal static void AddSqlite(this IServiceCollection services)
{
    // 移除原有的DbContext配置
    var commonDbOpt = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<CommonDbContext>));
    if (commonDbOpt != null) services.Remove(commonDbOpt);

    var myDbOpt = services.SingleOrDefault(d => d.ServiceType == typeof(DbContextOptions<MyDbContext>));
    if (myDbOpt != null) services.Remove(myDbOpt);

    // 移除原有的DbConnection注册
    var dbConn = services.SingleOrDefault(d => d.ServiceType == typeof(DbConnection));
    if (dbConn != null) services.Remove(dbConn);

    // 注册共享的内存连接,保持打开状态
    services.AddSingleton<DbConnection>(sp =>
    {
        var conn = new SqliteConnection("DataSource=:memory:");
        conn.Open();
        return conn;
    });

    // 重新注册CommonDbContext
    services.AddDbContext<CommonDbContext>((sp, options) =>
    {
        var conn = sp.GetRequiredService<DbConnection>();
        options.UseSqlite(conn);
    });

    // 重新注册MyDbContext
    services.AddDbContext<MyDbContext>((sp, options) =>
    {
        var conn = sp.GetRequiredService<DbConnection>();
        options.UseSqlite(conn);
        // 若需默认Schema,可在此配置:
        // options.UseSqlite(conn).UseSqlite(b => b.MigrationsHistoryTable("__EFMigrationsHistory", "dbo"));
    });
}

3. 调整TestDbContextFactory逻辑

确保返回的上下文是DI容器中正确配置的实例:

public class TestDbContextFactory : IDbContextFactory
{
    private readonly IServiceProvider _serviceProvider;

    public TestDbContextFactory(IServiceProvider serviceProvider)
    {
        _serviceProvider = serviceProvider;
    }
    
    public MyDbContext CreateMyDbContext(string? configKey, string? schemaName)
    {
        var context = _serviceProvider.GetRequiredService<MyDbContext>();
        // 若需动态设置Schema,可在此补充逻辑(如Context有对应方法)
        // context.SetDefaultSchema(schemaName ?? "dbo");
        return context;
    }
}

4. 修正测试初始化方法

确保在同一个作用域内完成两个上下文的表创建和数据填充:

[SetUp]
public void Setup()
{
    using var scope = _webApplicationFactory.Services.CreateScope();
    var scopedServices = scope.ServiceProvider;
    
    // 先获取两个上下文,确保共享同一连接
    var commonDb = scopedServices.GetRequiredService<CommonDbContext>();
    var myDb = scopedServices.GetRequiredService<MyDbContext>();

    // 初始化两个上下文的表结构
    commonDb.Database.EnsureCreated();
    myDb.Database.EnsureCreated();

    // 填充测试数据
    SeedDataClass.InitializeDbForTests(commonDb);
    SeedDataClass.InitializeDbForTests(myDb);
}

内容的提问来源于stack exchange,提问作者PalBo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 15:29:53