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

EF Core 5的InMemory数据库能否用于集成测试及报错解决

这个问题可以修复,不需要直接更换数据库模拟方案,你的问题确实和EF Core 5禁用隐式客户端计算的破坏性变更相关。

问题根源

EF Core 5开始默认禁止LINQ查询中无法被提供程序翻译的部分隐式落到客户端执行,你之前在EF Core 3中能正常运行,是因为当时InMemory提供程序隐式做了客户端计算兼容了自定义类型的比较逻辑,升级后该逻辑被禁用就会抛出翻译失败的错误。
更深层的原因是你实现的UUIdTypeMapperPlugin是针对关系型数据库的类型映射插件,而InMemory提供程序不会加载关系型的类型映射插件,因此在InMemory中无法识别UUId类型的相等比较逻辑,导致Join查询的表达式无法被翻译。


修复方案

方案1:快速兼容现有InMemory测试方案

只需给模型中的UUId属性全局配置值转换器和比较器,InMemory提供程序可以识别模型内配置的转换规则,无需修改现有测试代码:
可以直接在业务DbContext的OnModelCreating方法中添加全局配置,也可以单独为测试创建DbContext子类重写该方法,不影响正式环境代码:

protected override void OnModelCreating(ModelBuilder modelBuilder)
{
    // 全局为所有UUId类型属性配置转换和比较规则
    var uuidConverter = new ValueConverter<UUId, byte[]>(
        uuid => uuid.ToByteArray(),
        bytes => new UUId(bytes)
    );
    var uuidComparer = new ValueComparer<UUId>(
        (left, right) => left.Equals(right),
        uuid => uuid.GetHashCode(),
        uuid => uuid
    );

    foreach (var entityType in modelBuilder.Model.GetEntityTypes())
    {
        foreach (var property in entityType.GetProperties())
        {
            if (property.ClrType == typeof(UUId))
            {
                property.SetValueConverter(uuidConverter);
                property.SetValueComparer(uuidComparer);
            }
        }
    }

    // 原有模型配置逻辑
}

配置完成后InMemory就能正确识别UUId的比较逻辑,报错即可解决。


方案2:切换到更贴近生产的测试方案(解决多上下文建库问题)

如果担心InMemory和真实生产数据库行为有差异,想要切换到真实数据库测试,你提到的多上下文建库问题可以通过聚合上下文实现,步骤非常简单:

  1. 在测试项目中单独创建一个仅用于建库的统一DbContext,无需包含业务逻辑,只需要注册所有实体配置:
// 测试项目专用统一上下文
public class TestUnifiedDbContext : DbContext
{
    public TestUnifiedDbContext(DbContextOptions<TestUnifiedDbContext> options) : base(options)
    {
    }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        // 加载所有业务上下文所在程序集的实体配置
        modelBuilder.ApplyConfigurationsFromAssembly(typeof(RatingsContext).Assembly);
        // 如果有其他业务上下文,追加对应程序集即可
        // modelBuilder.ApplyConfigurationsFromAssembly(typeof(OtherBusinessContext).Assembly);
    }
}
  1. 测试启动时,仅用该统一上下文调用context.Database.EnsureCreated()完成一次建库,后续所有业务上下文直接连接该数据库即可,无需每个上下文单独建库。
  2. 速度问题可以通过使用SQLite内存模式、MySQL临时数据库配合用例结束后清表的逻辑解决,整体运行速度和InMemory差距极小,且测试结果更贴近生产行为。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 17:24:05