使用 out 参数在 NSubstitute 模拟方法中返回不同的值

returning different values in an NSubstitute mock method with an out parameter

给定一个模拟的方法...

public bool TryReceive(out T message, TimeSpan millisecondsToWait)

我尝试了一些变体,在任何一种情况下,lambda 表达式都会执行一次,并且再也不会执行。 NSubstitute 似乎 缓存第一个 return 值 ,并一遍又一遍地使用相同的值。

我已经试过了...

TCR @out;
var container = new AutoSubstitute();
var mb = container.Resolve<IMessageBuffer<TCR>>();
mb.TryReceive(out @out, Arg.Any<TimeSpan>()).Returns(
            _ => { _[0] = buy; return true; },
            _ => { _[0] = sell; return true; },
            _ => { _[0] = null; return false; });

我已经试过了:

        bool? bs = true;
        TCR @out;
        var container = new AutoSubstitute();
        var mb = container.Resolve<IMessageBuffer<TCR>>();
        mb.TryReceive(out @out, Arg.Any<TimeSpan>()).Returns(
            _ =>
            {
                if (bs == true)
                {
                    _[0] = buy;
                    bs = false;
                    return true;
                }
                if (bs == false)
                {
                    _[0] = sell;
                    bs = null;
                    return true;
                }
                _[0] = null;
                return false;
            });

我能想到的唯一选择是提供缓冲区的完整替代实现以用于测试目的。我的感觉是这样documentation,应该可以吧

编辑

我一直无法使用 NSubstitute 实现此功能,但是如果我使用

提供 IMessageBuffer<TCR> 的模拟实现
// mock buffer will return the necessary values by maintaining
// the relevant state internally.
container.Provide<IMessageBuffer<TCR>>(new MockBuffer());

它工作正常,所以这不是生命周期问题。不知何故,NSubstitute 似乎只在第一次调用模拟方法,并重用该值(或以 似乎 重用该值的方式运行)- 非常奇怪。

NSubstitute 在 outref 参数方面有些困难。

问题是当我们存根时:

mb.TryReceive(out @out, Arg.Any<TimeSpan>()).Returns(...)

这只会在@out为原始值时执行。这个值会在第一次调用时改变,所以 Returns lambda 不会再次执行(NSub 认为这是一个不同的、不匹配的调用)。

解决此问题的最简单方法是切换到 ReturnsForAnyArgs(...):

mb.TryReceive(out @out, Arg.Any<TimeSpan>()).ReturnsForAnyArgs(action0, action1, action2);

这将适用于所有 TryReceive 调用,无论参数值如何,因此 lambda 应该始终执行。这样做的缺点是,如果您只想 运行 用于第二个参数的特定值,那么您必须将该逻辑放在 lambda 中(而不是使用参数匹配器)。