为何NSubstitute.Return未被调用?集成测试代理配置异常排查
Returns()配置未生效的问题 我来帮你分析下这个棘手的问题——这种情况我之前也碰到过几次,大概率是NSubstitute的一些细节特性被忽略了。咱们一步步拆解:
最可能的原因:方法重载不匹配
先确认你的IRepository接口中,GetValueForEntity是否只有一个接收int参数的版本?如果存在其他重载(比如GetValueForEntity(long id)或者GetValueForEntity(Guid id)),那你用Arg.Any<int>()配置的规则只会匹配int参数的调用,而如果EntityFactory里实际调用的是另一个重载版本,你的断点自然不会触发,配置也不会生效。
你可以先暂时简化参数匹配逻辑,甚至直接针对所有调用配置:
proxyRepository .GetValueForEntity(Arg.Any<int>()) // 换成更简洁的写法,直接用参数传递,避免callInfo.Args()索引出错 .Returns(id => realRepository.GetValueForEntity(id));
检查配置顺序是否正确
NSubstitute的配置规则是先配置,后调用,如果在你配置Returns()之前,proxyRepository.GetValueForEntity已经被调用过(比如容器初始化过程中不小心触发了),那第一次调用会使用NSubstitute的默认返回值(引用类型返回null,值类型返回默认实例),后续的配置不会回溯生效。
建议你在创建proxyRepository之后,立刻完成所有规则配置,确保没有其他代码提前调用了这个方法。
留意默认返回值的“隐形干扰”
当你用Substitute.For<IRepository>()创建代理时,NSubstitute会自动为接口的所有方法生成默认返回值。如果你的GetValueForEntity返回的是值类型(比如自定义struct),默认返回值是该类型的空实例,这时候即使配置没生效,代码也不会抛出异常,只会返回默认值,这会让你误以为方法被调用了,但其实你的自定义逻辑根本没执行。
启用调试日志精准排查
如果以上方法都没用,可以开启NSubstitute的调试输出,直接查看它的匹配过程:
// 在测试开头添加这段代码,输出NSubstitute的匹配日志 NSubstitute.Core.SubstitutionContext.Current.Output(log => Console.WriteLine(log));
运行测试后,控制台会输出NSubstitute接收到的调用、尝试匹配的规则等细节,能帮你明确为什么Returns()配置没被触发。
补充:When().Do()和Returns()的匹配逻辑是一致的
你提到InsertValueForEntity用When().Do()生效了,而GetValueForEntity用Returns()没生效——其实两者的参数匹配逻辑是完全相同的,问题大概率不在API的选择上,还是匹配规则或执行顺序的问题。
内容的提问来源于stack exchange,提问作者Ben Collins

