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

使用NSubstitute验证Mock DbContext的Add方法调用失败问题

解决DbContext Add方法验证失败的问题

你遇到的核心问题是DbContext.Add是EF自带的非虚方法,NSubstitute无法拦截非虚方法的调用——哪怕实际代码执行了Add,Substitute也捕获不到这个调用行为,所以测试会提示无匹配调用。

以下是两种正确的验证方式:

方式一:验证对应DbSet的Add方法

业务代码中调用context.Add<ChangeLog>(entity)本质上会转调context.Set<ChangeLog>().Add(entity),因此可以mock对应的DbSet来验证:

// Mock ChangeLog对应的DbSet
var changeLogSet = Substitute.For<DbSet<ChangeLog>, IQueryable<ChangeLog>>();
var context = Substitute.For<LampContext>();
// 将mock的DbSet绑定到上下文
context.Set<ChangeLog>().Returns(changeLogSet);

// 调用触发Add操作的业务代码

// 验证DbSet的Add方法被调用1次,参数为任意ChangeLog实例
changeLogSet.Received(1).Add(Arg.Any<ChangeLog>());

方式二:通过接口抽象DbContext行为

定义包含Add方法的接口,让你的LampContext实现该接口,之后mock接口而非直接mock DbContext:

// 定义抽象接口
public interface ILampContext
{
    void Add<TEntity>(TEntity entity) where TEntity : class;
    // 根据业务需求添加其他需要的DbContext方法
}

// 让LampContext实现接口
public class LampContext : DbContext, ILampContext
{
    // 原有DbContext的实现代码
}

// 测试时mock接口
var context = Substitute.For<ILampContext>();

// 调用业务代码

// 直接验证接口的Add方法调用
context.Received(1).Add(Arg.Any<ChangeLog>());

注意事项

  • 方式一中要确保业务代码的Add调用对应到正确的DbSet类型;
  • 泛型方法验证时,Arg.Any<ChangeLog>的类型要与实际传入的实体类型完全匹配。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 20:21:04