给出一种模拟方法......
public bool TryReceive(out T message, TimeSpan millisecondsToWait)
我尝试了一些变体,在任何一种情况下, 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似乎只是第一次调用模拟方法,并重用该值(或以似乎重用该值的方式运行) - 非常奇怪。
答案 0 :(得分:1)
NSubstitute与out
和ref
参数有点挣扎。
问题是当我们存根时:
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中(而不是使用参数匹配器)。