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

单元测试EF Core派生DbContext时遇无法创建Product的DbSet问题求助

解决DbContext单元测试中"Cannot create a DbSet for 'Product'"错误

问题场景

对CoreDbContext(DbContext派生类)做单元测试时,持续收到错误:

Cannot create a DbSet for 'Product' because this type is not included in the model for the context

测试代码

[Fact]
public void GetAssync_Method_Called()
{
   var options = new DbContextOptionsBuilder<CoreDbContext>()
       //.UseModel()       USE MODEL
       .UseInMemoryDatabase(databaseName: "test")
       .Options;

    using (var context = new CoreDbContext(options))
    {
       context.Set<Product>(); // 试图这样添加实体?

       Expression<Func<Product, bool>> filter = x => !x.IsDeleted == 1;
       var result = GetAllAsNoTrackin(filter);

       Assert.Equal(1, result.Count());
    }
}

CoreDbContext代码

public class CoreDbContext : DbContext
{
   public CoreDbContext(DbContextOptions<CoreDbContext> options) : base(options)
   {
   }

   public IQueryable<Product> GetAllAsNoTrackin(Expression<Func<Product, bool>> filter)
   {
       var dbSet = Set<Product>().AsNoTracking(); // 报错位置
       // 更多代码...
   }
 }

错误原因

EF Core的上下文模型中没有包含Product实体,调用Set<Product>()时无法识别该类型,导致报错。测试代码里的context.Set<Product>()并不能将实体添加到上下文模型中,模型是在上下文初始化阶段确定的。

解决方案

1. 显式声明DbSet属性

在CoreDbContext中添加DbSet<Product>属性,EF Core会自动将该实体纳入模型:

public class CoreDbContext : DbContext
{
   public CoreDbContext(DbContextOptions<CoreDbContext> options) : base(options)
   {
   }

   // 添加DbSet属性,让EF Core识别Product实体
   public DbSet<Product> Products { get; set; }

   public IQueryable<Product> GetAllAsNoTrackin(Expression<Func<Product, bool>> filter)
   {
       var dbSet = Set<Product>().AsNoTracking();
       // 后续代码...
   }
}

2. 在OnModelCreating中配置实体

如果不想显式声明DbSet,可以重写OnModelCreating方法,直接注册Product实体:

public class CoreDbContext : DbContext
{
   public CoreDbContext(DbContextOptions<CoreDbContext> options) : base(options)
   {
   }

   protected override void OnModelCreating(ModelBuilder modelBuilder)
   {
       // 注册Product实体到模型
       modelBuilder.Entity<Product>();
   }

   public IQueryable<Product> GetAllAsNoTrackin(Expression<Func<Product, bool>> filter)
   {
       var dbSet = Set<Product>().AsNoTracking();
       // 后续代码...
   }
}

3. 使用UseModel方法(动态构建模型)

如果需要预先构建模型并传入上下文(替代OnModelCreating逻辑),可以这样使用UseModel:

[Fact]
public void GetAssync_Method_Called()
{
   // 先构建包含Product的模型
   var modelBuilder = new ModelBuilder();
   modelBuilder.Entity<Product>();
   var model = modelBuilder.Model;

   var options = new DbContextOptionsBuilder<CoreDbContext>()
       .UseModel(model) // 使用预先构建的模型
       .UseInMemoryDatabase(databaseName: "test")
       .Options;

    using (var context = new CoreDbContext(options))
    {
       // 添加测试数据
       context.Set<Product>().Add(new Product { IsDeleted = false });
       context.SaveChanges();

       Expression<Func<Product, bool>> filter = x => !x.IsDeleted;
       var result = context.GetAllAsNoTrackin(filter);

       Assert.Equal(1, result.Count());
    }
}

注意:UseModel是用来指定上下文使用的预构建模型,无法在上下文创建后动态添加实体,模型一旦确定就无法修改。

测试代码修正

确保上下文包含Product实体后,测试代码中需要添加测试数据才能验证逻辑:

[Fact]
public void GetAssync_Method_Called()
{
   var options = new DbContextOptionsBuilder<CoreDbContext>()
       .UseInMemoryDatabase(databaseName: "test")
       .Options;

    using (var context = new CoreDbContext(options))
    {
       // 添加测试数据到上下文
       context.Products.Add(new Product { IsDeleted = false });
       context.SaveChanges();

       Expression<Func<Product, bool>> filter = x => !x.IsDeleted;
       var result = context.GetAllAsNoTrackin(filter);

       Assert.Equal(1, result.Count());
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.16 07:20:59