【问题标题】:returning different values in an NSubstitute mock method with an out parameter在带有 out 参数的 NSubstitute 模拟方法中返回不同的值
【发布时间】:2016-06-28 11:52:47
【问题描述】:

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

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&lt;TCR&gt; 提供模拟实现

// mock buffer will return the necessary values by maintaining
// the relevant state internally.
container.Provide<IMessageBuffer<TCR>>(new MockBuffer());

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

【问题讨论】:

  • 对不起,我正在使用 AutoContainer,它提供了 Subsitute。对于,我已将该代码添加到问题中。 AutoContainer 只提供了 Substitute.For,并将结果保存在容器中,以便每次需要依赖时解析相同的替换。
  • 您可以在每个匿名代码块中添加一些制动点,以检查实际调用的是哪个。
  • 我有,奇怪的是 lambda 被调用一次,而且只调用一次。之后,每次都提供相同的结果。
  • 当您使用上面显示的第二种方法时,它可以工作吗?
  • 不,我已经开始四处挖掘,我认为我有一些生命周期问题。我觉得这个问题比 NSubstitute 的问题更复杂

标签: c# unit-testing nsubstitute


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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多