如何用Xunit和Moq模拟Entity DbContext插入?遇空引用错误
解决Moq模拟DbContext时Set()空引用的问题
我来帮你搞定这个单元测试里的空引用问题!你遇到的错误核心原因很明确:你Mock出来的DbContext,它的Set<T>()方法没有被正确配置,调用时返回了null,所以当ARepository执行Context.Set<T>().Add(entity)时,自然就触发了空引用异常。
下面是一步步的修复方案,亲测有效:
1. 先Mock一个可用的DbSet
首先得给你的实体类(比如假设是YourEntity)创建一个Mock的DbSet<T>实例,这样后续DbContext才能返回它:
var mockDbSet = new Mock<DbSet<YourEntity>>();
2. 让Mock DbContext返回这个DbSet
接下来关键的一步:配置你的Mock DbContext,让它在调用Set<YourEntity>()时返回上面创建的mockDbSet,而不是默认的null:
var mockContext = new Mock<YourDbContext>(); // 重点:Setup Set<T>方法的返回值 mockContext.Setup(c => c.Set<YourEntity>()).Returns(mockDbSet.Object);
3. 编写完整的单元测试验证Add操作
现在把这个Mock的DbContext注入到你的ARepository里,执行Add方法后,就能验证是否正确调用了Add操作:
[Fact] public void Add_WantToWork() { // Arrange var mockDbSet = new Mock<DbSet<YourEntity>>(); var mockContext = new Mock<YourDbContext>(); mockContext.Setup(c => c.Set<YourEntity>()).Returns(mockDbSet.Object); var repository = new ARepository(mockContext.Object); var testEntity = new YourEntity { /* 这里设置你的测试实体属性 */ }; // Act repository.Add(testEntity); // Assert // 验证DbSet的Add方法是否被精确调用了一次,参数就是我们的测试实体 mockDbSet.Verify(d => d.Add(testEntity), Times.Once); }
额外小技巧
- 如果你的
ARepository是泛型仓库,只需要把上面的YourEntity替换成泛型参数即可,适配所有实体类。 - 要是你还需要验证
SaveChanges()是否被调用,可以再加一段配置:
然后在Assert阶段验证:// 配置SaveChanges返回1,表示保存成功 mockContext.Setup(c => c.SaveChanges()).Returns(1);mockContext.Verify(c => c.SaveChanges(), Times.Once);
内容的提问来源于stack exchange,提问作者Kevin C.
相关产品推荐
相关产品推荐

