Издевательское итеративное поведение

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

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

internal class LineReader : ILineReader { private readonly IList _lines; private int _countOfLines; private int _place; public LineReader(IList 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); } } 

EDIT Неполный единичный тест :

  [Test] public void Test() { IList lineListForMock = new List() { "A", "B", "C" }; MockRepository mockRepository = new MockRepository(); ILineReader lineReader = mockRepository.Stub(); //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); } 

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

 var enumerator = new List { "A", "B", "C" }.GetEnumerator(); var lineReader = MockRepository.GenerateStub(); 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()); 

Это похоже на трюк:

 [TestFixture] public sealed class TestIterativeRhinoReturn { private int _count; private int _countOfLines; private IList _lines; private string _currentLine; [SetUp] public void SetUp() { _count = -1; _lines= new List() { "A", "B", "C", null }; _countOfLines = _lines.Count; _currentLine = null; } [Test] public void Test() { MockRepository mockRepository = new MockRepository(); ILineReader lineReader = mockRepository.DynamicMock(); 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 (). Теперь возвращаемое значение изменяется для каждого чтения.

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

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

Затем вы можете контролировать точные значения, которые вы после.