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

时间:2016-06-28 11:52:48

标签: c# unit-testing nsubstitute

给出一种模拟方法......

public bool TryReceive(out T message, TimeSpan millisecondsToWait)
  • 我希望在前两个电话上设置不同的消息,然后返回 真正。
  • 后续调用返回false。

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

我试过这个......

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似乎只是第一次调用模拟方法,并重用该值(或以似乎重用该值的方式运行) - 非常奇怪。

1 个答案:

答案 0 :(得分:1)

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中(而不是使用参数匹配器)。