Издевательское итеративное поведение - PullRequest
0 голосов
/ 22 июня 2011

У меня есть интерфейс с итеративным поведением, и у меня возникают проблемы с имитацией этого в Rhinomocks. Пример интерфейса и класса - очень простая версия моей проблемы.

Каждый раз, когда вызывается LineReader.Read (), LineReader.CurrentLine () должна возвращать другое значение - следующую строку. Такое поведение я до сих пор не смог воспроизвести в издевательстве. Таким образом, это стало моим маленьким хобби-проектом, к которому я время от времени возвращаюсь. Я надеюсь, что вы можете помочь мне сделать еще один шаг.

internal class LineReader : ILineReader
{
    private readonly IList<string> _lines;
    private int _countOfLines;
    private int _place; 

    public LineReader(IList<string> lines)
    {
        _lines = lines;
        _countOfLines = lines.Count;
        _place = 0; 
    }

    public string CurrentLine()
    {
        if (_place<_countOfLines)
        {
            return _lines[_place];
        }
        else
        {
            return null; 
        }

    }

    public bool ReadLine()
    {
        _place++;
        return (_place < _countOfLines);
    }

}

РЕДАКТИРОВАТЬ Добавлен неполный модульный тест :

    [Test]
    public void Test()
    {
        IList<string> lineListForMock = new List<string>()
                                            {
                                                "A",
                                                "B",
                                                "C"
                                            };

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

        //Setup the values here

        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 read1 = lineReader.ReadLine();
        Assert.That(read1, Is.False);


    }

Ответы [ 3 ]

4 голосов
/ 24 июня 2011

Это все, что вам нужно:

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());
2 голосов
/ 22 июня 2011

Похоже, это помогает:

[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]; 
    }

Обратите внимание на строки:

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

и методы делегата ReadRecord () и ReturnString ().Теперь возвращаемое значение меняется для каждого чтения.

1 голос
/ 22 июня 2011

Я не знаю, есть ли у меня последняя версия rhino-mocks, но мой метод .Return не требует делегата / действия - что-то, что могло бы быть полезным для выполнения того, что вы хотите.

Однако, похоже, вы ближе к тестированию на основе состояния, поэтому, возможно, просто создайте свою собственную фиктивную реализацию для тестирования (или заглушки, или фальшивки - выбираете:)

Тогда вы можете контролировать точные значенияВы после.

...