如何为Entity Framework Core模拟DbSet.Add()方法?
EF Core模拟DbContext时Add方法不生效的解决办法
你当前用ReturnsDbSet模拟的DbSet仅提供查询数据的能力,不会自动处理Add这类修改操作,因此需要手动模拟Add方法,同时解决返回EntityEntry<Book>的问题,以下是两种简单可行的方案:
方案一:用Moq直接模拟Add方法并返回Mock的EntityEntry
无需直接实例化EntityEntry<Book>,用Moq创建它的模拟对象即可:
Mock<MyDbContext> fakeDbContext = new Mock<MyDbContext>(); List<Book> availableBooks = new List<Book>(); // 已在别处填充数据 // 创建EntityEntry的模拟对象 var mockEntityEntry = new Mock<EntityEntry<Book>>(); // 模拟BookRepository的Add方法:执行添加到集合,同时返回模拟的EntityEntry fakeDbContext.Setup(ct => ct.BookRepository.Add(It.IsAny<Book>())) .Callback<Book>(newBook => availableBooks.Add(newBook)) .Returns(mockEntityEntry.Object); // 保留原有的ReturnsDbSet设置,确保查询能正常获取数据 fakeDbContext.Setup(ct => ct.BookRepository).ReturnsDbSet(availableBooks);
调用fakeDbContext.BookRepository.Add(newBook)时,newBook会被加入availableBooks集合,同时返回符合要求的EntityEntry<Book>对象。
方案二:自定义模拟DbSet类
如果需要模拟更多DbSet操作(比如Remove、Update),可以自行实现继承DbSet<T>的类,直接操作内存集合:
public class InMemoryDbSet<T> : DbSet<T> where T : class { private readonly List<T> _innerList; public InMemoryDbSet(List<T> innerList) { _innerList = innerList; } // 重写Add方法,添加到内存集合并返回实体 public override T Add(T entity) { _innerList.Add(entity); return entity; } // 支持返回EntityEntry的Add扩展方法 public new EntityEntry<T> Add(T entity) { _innerList.Add(entity); return new Mock<EntityEntry<T>>().Object; } // 按需重写查询方法,确保查询行为符合预期 public override List<T> ToList() { return _innerList.ToList(); } }
使用时替换原有的ReturnsDbSet:
fakeDbContext.Setup(ct => ct.BookRepository) .Returns(new InMemoryDbSet<Book>(availableBooks));
关键说明
ReturnsDbSet仅为DbSet提供查询数据源,不会自动将增删改操作绑定到内存集合,必须手动模拟这些方法的行为,才能让修改操作同步到availableBooks列表中。
内容的提问来源于stack exchange,提问作者Jean-David Lanz
相关产品推荐
相关产品推荐

