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的模拟逻辑。修正方案
- 若目标方法是静态方法:给
testMethod/testMethod2加上static修饰符,原代码即可正常工作。 - 若目标方法是实例方法:改用
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
相关产品推荐
相关产品推荐

