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

使用Moq测试MyData类时GetData方法未执行且返回null

问题根因定位

你遇到的现象和异步调用写法无关,本质是Moq的默认拦截规则触发的典型踩坑:

  • Moq创建Mock实例时,会对被Mock类的所有virtual成员(无论public、protected访问修饰符)启用默认拦截:如果没有显式配置该成员的行为,就会直接拦截调用,返回成员类型的默认值(对应Task<string>的默认值就是null),完全不会执行原类中定义的方法逻辑。
  • 你代码中作为测试目标的GetData方法本身就是public virtual方法,创建出来的Mock实例会直接拦截这个方法的调用,根本不会触发原类里写的GetData逻辑,自然方法内部的断点无法命中,最终直接返回null。
修复方案

只要调整Mock的配置,让被拦截的GetData方法走原类的真实逻辑,同时保留对两个依赖方法的Mock配置即可:

  • 方式一:在Mock初始化阶段开启CallBase = true,告知Moq对未显式设置行为的成员,默认调用原类的实现
  • 方式二:不对整个Mock开启全局CallBase,只针对GetData方法单独配置调用原实现,精准控制行为
  • 修正后的测试代码示例:
public void TestData()
{
    string testData = "some data";
    Mock<MyData> dataMock = new Mock<MyData>("path")
    {
        // 开启基类原方法调用
        CallBase = true
    };
    // 保留原有对依赖的受保护方法的Mock配置
    dataMock.Protected().Setup<bool>("IsDataExpired").Returns(true);
    dataMock.Protected().Setup<Task<string>>("CreateData").ReturnsAsync(testData);
    
    var dataRes = dataMock.Object.GetData().Result;
    Assert.IsNotNull(dataRes);
    Assert.AreEqual(testData, dataRes);
}
  • 注意点:如果不想全局开启CallBase,也可以单独对GetData配置:
dataMock.Setup(m => m.GetData()).CallBase();

这种写法的效果和全局开启CallBase一致,只对GetData方法放行原逻辑调用,其他未配置的虚方法还是走默认拦截规则。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.27 11:57:03