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

使用Moq模拟带out参数的C#方法并实现多次调用返回不同值

使用Moq模拟带out参数的C#方法并实现多次调用返回不同值

我来帮你搞定Moq处理out参数的这两个问题,实操性的例子给你安排上:

1. 正确处理out参数的Setup

在Moq里处理out参数,核心是用It.Ref<T>.IsAny来匹配任意的out参数占位,然后通过Callback给这个out参数赋值,再用Returns指定方法的返回值(也就是你的bool类型结果)。

举个基础的例子:

// 先创建你的接口/类的Mock实例
var mockService = new Mock<IYourService>();

// 模拟TryGetNext方法:返回true,同时给out参数赋值一个具体的Bestellung对象
mockService.Setup(x => x.TryGetNext(out It.Ref<Bestellung?>.IsAny))
    .Returns(true)
    .Callback(() => 
        It.Ref<Bestellung?>.Value = new Bestellung { Id = 1, /* 其他属性按需初始化 */ }
    );

如果你的场景需要匹配特定的out参数值(不过这种情况很少见),也可以直接在Setup里指定,但用It.Ref的方式更通用,能覆盖大部分场景。

2. 实现多次调用返回不同值和不同out参数

想要让Mock在每次调用时返回不同结果、给out参数赋不同值,有两种常用方式:

方式一:用SetupSequence按顺序定义

这种方式适合你已经明确知道每次调用的预期结果的场景,直接按调用顺序依次配置:

var mockService = new Mock<IYourService>();
var firstOrder = new Bestellung { Id = 1 };
var secondOrder = new Bestellung { Id = 2 };

mockService.SetupSequence(x => x.TryGetNext(out It.Ref<Bestellung?>.IsAny))
    // 第一次调用:返回true,out参数赋值firstOrder
    .Returns(true)
    .Callback(() => It.Ref<Bestellung?>.Value = firstOrder)
    // 第二次调用:返回true,out参数赋值secondOrder
    .Returns(true)
    .Callback(() => It.Ref<Bestellung?>.Value = secondOrder)
    // 第三次及之后所有调用:返回false,out参数设为null
    .Returns(false)
    .Callback(() => It.Ref<Bestellung?>.Value = null);

方式二:用计数器+动态逻辑

如果你的调用次数不确定,或者需要根据调用次数动态生成out参数值,就可以用计数器结合回调来实现:

var mockService = new Mock<IYourService>();
var callCounter = 0;
// 提前准备好每次调用要返回的out参数值列表
var orderList = new List<Bestellung?> 
{ 
    new Bestellung { Id = 1 }, 
    new Bestellung { Id = 2 }, 
    null 
};

mockService.Setup(x => x.TryGetNext(out It.Ref<Bestellung?>.IsAny))
    // 动态返回bool结果:只要当前索引的order不为null就返回true
    .Returns(() => 
    {
        if (callCounter >= orderList.Count) return false;
        return orderList[callCounter] != null;
    })
    // 给out参数赋值当前索引对应的order
    .Callback(() => 
    {
        if (callCounter < orderList.Count)
        {
            It.Ref<Bestellung?>.Value = orderList[callCounter];
        }
        callCounter++;
    });

这样每次调用Mock的TryGetNext方法时,计数器会自动递增,依次取出列表里的赋值,直到列表用完后返回false。

备注:内容来源于stack exchange,提问作者FlorianD

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 16:08:14