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

使用Moq测试API服务报错Value cannot be null (Parameter 'source')如何解决

错误产生原因

你遇到的Value cannot be null. (Parameter 'source')错误是LINQ操作触发的典型异常:当调用LINQ方法(比如Where、Select、ToList等)时,操作的数据源对象为null就会抛出该错误。对应到你的测试代码,具体原因如下:

  • 核心原因:你虽然构造了Mock<DbSet<MyModel>>对象,但没有为Mock的LiveDbContext配置对应MyModel实体的DbSet属性返回值。你的GetStaffByCentre方法内部必然是调用了LiveDbContext中类似DbSet<MyModel> Staff/DbSet<MyModel> MyModels的属性来做查询,你没有对该属性做Setup,代码运行时拿到的DbSet就是null,后续LINQ查询就会抛出source为null的错误。
  • 无效配置干扰:你写的mockContext.Setup(m => m.Add(models)).Callback<DbSet<MyModel>>(mockDbSet.Object.AddRange);是完全错误的配置,既不符合Mock DbContext的逻辑,参数匹配规则也不成立,属于完全无效的冗余代码,可能引入额外异常。
  • 潜在异步问题:从你调用.Result可以看出GetStaffByCentre是异步方法,你当前只配置了同步IQueryable的相关成员,就算解决了DbSet为null的问题,后续如果方法内部用到了EF异步查询方法(比如ToListAsync)也会抛出不支持异步操作的错误。
修复方案

按照以下步骤调整测试代码即可:

  1. 给Mock的DbContext配置对应DbSet属性的返回值,假设你的LiveDbContext中对应MyModel的DbSet属性名为MyModels,添加以下配置:
// 注意替换MyModels为你DbContext中实际的属性名
mockContext.Setup(c => c.MyModels).Returns(mockDbSet.Object);
  1. 删除无效的冗余配置行:
// 直接删掉这行代码即可
mockContext.Setup(m => m.Add(models)).Callback<DbSet<MyModel>>(mockDbSet.Object.AddRange);
  1. (可选,适配异步查询)如果你的业务代码用到了EF异步查询方法,推荐安装MockQueryable.MoqNuget包简化配置,无需手动编写IQueryable相关的Setup代码,调整后的Mock DbSet代码如下:
var models = new List<MyModel> {
    new MyModel
    {
        Id = 1,
        Name = "John Smith",
        Status = "Engineer",
        Centre = 9999
    },
    new MyModel
    {
        Id = 2,
        Name = "Jane Doe",
        Status = "Manager",
        Centre = 9999
    } 
};
// 直接通过扩展方法生成适配同步+异步的Mock DbSet
var mockDbSet = models.BuildMockDbSet();
mockContext.Setup(c => c.MyModels).Returns(mockDbSet.Object);

调整完成后重新运行测试即可解决当前报错。另外注意你的测试数据里有2条Centre=9999的记录,断言Assert.AreEqual(1, result.Count)大概率会失败,需要根据你的业务逻辑调整测试数据或者断言值。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 03:24:04