Mocking iterative behaviour

若如初见. 提交于 2019-12-02 12:29:16

This is all you need:

var enumerator = new List<string> { "A", "B", "C" }.GetEnumerator();
var lineReader = MockRepository.GenerateStub<ILineReader>();

lineReader.Stub(x => x.CurrentLine())
    .Return("ignored")
    .WhenCalled(x => x.ReturnValue = enumerator.Current);

lineReader.Stub(x => x.ReadLine())
    .Return(false) // will be ignored
    .WhenCalled(x => x.ReturnValue = enumerator.MoveNext());

This seems to do the trick:

[TestFixture]
public sealed class TestIterativeRhinoReturn
{
    private int _count;
    private int _countOfLines; 
    private IList<string> _lines;
    private string _currentLine; 
    [SetUp]
    public void SetUp()
    {
        _count = -1;

        _lines= new List<string>()
                                            {
                                                "A",
                                                "B",
                                                "C",
                                                null
                                            };


        _countOfLines = _lines.Count;
        _currentLine = null; 
    }


    [Test]
    public void Test()
    {

        MockRepository mockRepository = new MockRepository();
        ILineReader lineReader = mockRepository.DynamicMock<ILineReader>();

        lineReader.Stub(r => r.ReadLine()).Callback(new ReadLineDelegate(ReadRecord)).Return(_count < _countOfLines);
        lineReader.Stub(r => r.CurrentLine()).Do(new CurrentStringDelegate(ReturnString)).Return(_currentLine);

        mockRepository.ReplayAll();

        bool read1 = lineReader.ReadLine();
        Assert.That(read1, Is.True);
        Assert.That(lineReader.CurrentLine(), Is.EqualTo("A"));

        bool read2 = lineReader.ReadLine();
        Assert.That(read2, Is.True);
        Assert.That(lineReader.CurrentLine(), Is.EqualTo("B"));

        bool read3 = lineReader.ReadLine();
        Assert.That(read3, Is.True);
        Assert.That(lineReader.CurrentLine(), Is.EqualTo("C"));

        bool read4 = lineReader.ReadLine();
        Assert.That(read4, Is.False);
        Assert.That(lineReader.CurrentLine(), Is.Null);


    }


    public delegate bool ReadLineDelegate();

    private bool ReadRecord()
    {
        _count++;
        return (_lines[_count]!=null);
    }

    public delegate string CurrentStringDelegate(); 

    private string ReturnString()
    {
        return _lines[_count]; 
    }

Notice the Lines:

        lineReader.Stub(r => r.ReadLine()).Callback(new ReadLineDelegate(ReadRecord)).Return(_count < _countOfLines);
        lineReader.Stub(r => r.CurrentLine()).Do(new CurrentStringDelegate(ReturnString)).Return(_currentLine);

and the Delegate methods ReadRecord() and ReturnString(). Now the returnvalue changes for each read.

I don't know if I have the latest version of rhino-mocks but my .Return method does not take a delegate / action --- something that may have been useful for doing what you want.

However, you seem to be closer to state-based testing here so maybe just create your own mock implementation for testing (or stub, or fake --- you choose :)

Then you can control the exact values you are after.

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