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

如何在C#单元测试中为Mock同一方法配置不同入参的调用规则

问题原因

这是C#的循环变量闭包捕获特性导致的问题:for循环中声明的count变量在整个循环周期内是同一个实例,你在Setup的Lambda表达式里直接引用count时,所有配置实际捕获的都是同一个变量。循环结束后count的值为3,最终所有Setup匹配的参数都变成了abc_3,自然只有最后一次调用能匹配成功。

解决方案

方案1:循环内新增临时变量固定迭代值

只需要在循环内部新增临时变量存储当前迭代的count值,就能避免闭包捕获同一变量的问题,你的原有逻辑只需要改两行:

var printerMock = new Mock<IMyPrinter>(MockBehavior.Loose);
for (var count = 0; count < 4; count++)
{
    // 新增临时变量,每次迭代都会生成独立的实例
    var currentCount = count;
    printerMock.Setup(_ => _.Print($"abc_{currentCount}"));
}

var underTest = new MyObject();
underTest.Printer = printerMock.Object;

underTest.foo();
printerMock.VerifyAll();

方案2:直接验证调用,无需提前配置

如果你只需要验证Print的调用是否符合预期,不需要提前Setup模拟行为,直接用Verify做批量校验更简洁:

var printerMock = new Mock<IMyPrinter>(MockBehavior.Loose);
var underTest = new MyObject { Printer = printerMock.Object };

underTest.foo();

// 逐个验证每个参数的调用次数为1
for (var count = 0; count < 4; count++)
{
    var currentCount = count;
    printerMock.Verify(_ => _.Print($"abc_{currentCount}"), Times.Once);
}

方案3:批量捕获所有参数统一断言

如果需要对所有传入的参数做批量校验,可以用Moq的Capture功能捕获所有调用参数,再一次性做断言:

var printerMock = new Mock<IMyPrinter>(MockBehavior.Loose);
var receivedMessages = new List<string>();
// 捕获所有调用Print方法传入的参数
printerMock.Setup(_ => _.Print(Capture.In(receivedMessages)));

var underTest = new MyObject { Printer = printerMock.Object };
underTest.foo();

// 断言捕获到的参数和预期完全一致
var expectedMessages = Enumerable.Range(0, 4).Select(c => $"abc_{c}");
Assert.Equal(expectedMessages, receivedMessages);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 13:45:00