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

Moq模拟方法异常:未返回Setup定义委托,反而返回测试方法委托

问题

我为ICommandActionsProvider接口的GetDelegateByCommandNameWithoutParams方法创建了Moq模拟,期望根据输入的commandName参数返回对应委托,Setup代码如下:

actionsProvider
  .Setup(x => x.GetDelegateByCommandNameWithoutParams(It.IsAny<string>()))
  .Returns((string x) =>
  {
      if (x == testCommand)
         return Delegate.CreateDelegate(typeof(Func<int>),
             typeof(ExecuteCodeLinesCommandTests).GetMethod(testMethod));
      else if (x == testCommand2)
         return Delegate.CreateDelegate(typeof(Func<int, int, int, int>),
             typeof(ExecuteCodeLinesCommandTests).GetMethod(testMethod2));
      else return null;

  });

接口定义:

public interface ICommandActionsProvider
{
   public Delegate? GetDelegateByCommandNameWithoutParams(string commandName);
}

调用代码:

Delegate? del = commandActionProvider.GetDelegateByCommandNameWithoutParams(commandName);

但调用时未返回Setup定义的委托,反而返回测试方法的委托。我曾尝试在Returns中返回单一固定值,此时模拟正常生效,使用动态委托逻辑则出现该问题,请问原因是什么?

原因分析与解决方案
  • 核心原因:Delegate.CreateDelegate重载使用错误
    你当前用的Delegate.CreateDelegate(Type, MethodInfo)重载,要求目标方法是静态方法。如果testMethod/testMethod2是实例方法,这个重载会隐式绑定测试类的当前实例(也就是ExecuteCodeLinesCommandTests的测试实例),导致返回的委托直接指向测试类的真实实例方法,而非你期望的模拟返回结果。

  • 验证方向
    先检查testMethod和testMethod2是否标记为static。如果是实例方法,CreateDelegate会自动捕获当前测试实例,直接关联到真实方法,跳过Moq的模拟逻辑。

  • 修正方案

    1. 若目标方法是静态方法:给testMethod/testMethod2加上static修饰符,原代码即可正常工作。
    2. 若目标方法是实例方法:改用Delegate.CreateDelegate(Type, object, MethodInfo)重载,明确传入实例对象。示例代码:
actionsProvider
  .Setup(x => x.GetDelegateByCommandNameWithoutParams(It.IsAny<string>()))
  .Returns((string x) =>
  {
      if (x == testCommand)
      {
          var method = typeof(ExecuteCodeLinesCommandTests).GetMethod(testMethod);
          return Delegate.CreateDelegate(typeof(Func<int>), this, method); // 传入当前测试实例
      }
      else if (x == testCommand2)
      {
          var method = typeof(ExecuteCodeLinesCommandTests).GetMethod(testMethod2);
          return Delegate.CreateDelegate(typeof(Func<int, int, int, int>), this, method);
      }
      else return null;
  });

另外还要核对testCommand、testCommand2和调用时传入的commandName是否完全一致(包括大小写、空格),字符串不匹配会进入else分支返回null,可能触发真实方法的调用逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 20:40:28