使用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
相关产品推荐
相关产品推荐

