Не удается заставить RhinoMock перебирать DataReader - PullRequest
2 голосов
/ 24 мая 2011

Я пытаюсь смоделировать IDataReader с помощью RhinoMocks, но мне трудно заставить его перебирать DataRows.Вот что я сделал до сих пор:

[TestFixture]
public sealed class TestStubbedDataReader
{
    private int currentRowIdx;  //The current position in the datareader
    private bool notAtEnd;      //Return value of the Reader.Read method
    private int countOfRows;    //Count of rows in the dataReader

    private IList<IDataRecord> rows;    //The datarecords that the reader should iterate through


    [Test]
    public void TestDataReader()
    {

        //Mock the reader 
        MockRepository mockRepository = new MockRepository();
        IDataReader reader = mockRepository.Stub<IDataReader>();

        //Build a list of IDataRecords to for the datareader with two records. 
        //It mocks a simple table with a Int32 Id field and a string Name field.             
        rows = new List<IDataRecord>()
                              {
                                  new RowBuilder().WithValues(1, "AAA").Build(),
                                  new RowBuilder().WithValues(1, "BBB").Build()
                              };

        //Initializing variables for iteration
        currentRowIdx = 0;
        notAtEnd = true;
        countOfRows = rows.Count;

        //NOTE: It is probably here I am doing something wrong!!
        //Seting  up results for for reading the fields of the current record. 
        SetupResult.For(reader.GetInt32(0)).Return(rows[currentRowIdx].GetInt32(0));
        SetupResult.For(reader.GetString(1)).Return(rows[currentRowIdx].GetString(1));

        //Seting up returnValue for Reader.Read(). 
        //Call back increases the currentRowIdx or sets notAtEnd flag to False
        SetupResult.For(reader.Read()).Return(notAtEnd).Callback(new CallBackDelegate(MoveToNextRecord));

        mockRepository.ReplayAll();


        Int32 previousId = -1; 
        string previousName = string.Empty; 

        //Here I iterate through the DataReader.  
        while (reader.Read())
        {
            Console.WriteLine("Read ID:  " + reader.GetInt32(0) + " Name: " + reader.GetString(1));
            //dataValueObjects.Add(new ToxDataValueObject(reader));
            Console.WriteLine("Read");

            Assert.That(reader.GetInt32(0), !Is.EqualTo(previousId), "Id is the same as in the previous record");
            Assert.That(reader.GetString(1), !Is.EqualTo(previousName), "Name is the same as in the previous record");

            previousId = reader.GetInt32(0);
            previousName= reader.GetString(1); 

        }

    }


    public delegate bool CallBackDelegate(); 


    private bool MoveToNextRecord()
    {
        if (currentRowIdx<= countOfRows) //Not at the end yet; increas
        {
            currentRowIdx++; 
        }
        else                            //At the end. Next time, Reader.Read should return False
        {
            notAtEnd = false;
        }

        return notAtEnd; 
    }



}


//Builder for DataRows
internal class RowBuilder
{
    private MockRepository _mockRepository;
    private IDataRecord _dataRecord;

    public RowBuilder()
    {
        //Initialise and create stubbed datarecord. 
        _mockRepository = new MockRepository();
        _dataRecord = _mockRepository.Stub<IDataRecord>();
    }

    //Set return values, and return builder
    public RowBuilder WithValues(int id, string name)
    {
        SetupResult.For(_dataRecord.GetInt32(0)).Return(id);
        SetupResult.For(_dataRecord.GetString(1)).Return(name);
        return this;
    }


    //Return the mocked DataRow
    public IDataRecord Build()
    {
        _mockRepository.ReplayAll();
        return _dataRecord; 
    }
}

Читатель зацикливается дважды, как и предполагалось, но возвращаемые значения второй итерации идентичны первой.Что должно быть сделано ???

1 Ответ

3 голосов
/ 24 мая 2011

Мое предложение: избегать насмешливых компонентов с потенциально сложным (и скрытым) поведением .Вместо этого определите интерфейс адаптера, который соответствует вашим потребностям, менее общим способом и используйте его в своем коде вместо IDataReader.Затем смоделируйте этот интерфейс, что должно быть гораздо более простой задачей.

В рабочем коде определите и используйте реализацию интерфейса адаптера, которая работает с реальными IDataReader s.

...