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

对着背影说爱祢 提交于 2019-12-14 02:05:20

问题


Given a method with which to mock...

public bool TryReceive(out T message, TimeSpan millisecondsToWait)
  • I wish to set different messages on the first two calls, and return true.
  • Subsequent calls return false.

I have tried a few variations, and in either case, the lambda expression is executed once, and never again. NSubstitute seems to be caching the first return value, and using the same value over and over.

I have tried this...

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; });

and I have tried this:

        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;
            });

The only option I can think of is to provide a complete substitute implementation of the buffer for test purposes. My feeling is that given this documentation, it should be possible.

edit

I have been unable to get this working using NSubstitute, however if I provide a mock implementation of the IMessageBuffer<TCR> using

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

it works correctly, so it's not a lifetimescope issue. Somehow NSubstitute seems to be calling the mocked out method only the first time, and reusing the value (or operating in such a way that it seems to reuse the value) - very strange.


回答1:


NSubstitute struggles a bit with out and ref parameters.

The problem is that when we stub:

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

this will only execute when @out is the original value. This value will change the first time it is called, so the Returns lambda won't execute again (NSub thinks it is a different, non-matching call).

The easiest way to work-around this is to switch to ReturnsForAnyArgs(...):

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

This will work for all TryReceive calls, regardless of the parameter values, so the lambda should always execute. The downside of this is that if you want this to only run for specific values of the second argument then you'll have to put that logic inside the lambda (rather than using an argument matcher).



来源:https://stackoverflow.com/questions/38075513/returning-different-values-in-an-nsubstitute-mock-method-with-an-out-parameter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!