开发者

Can't get RhinoMock to iterate throug a DataReader

I am trying to mock IDataReader with RhinoMocks, but I am having a hard time making it iterate through the DataRows. Here is what I have done so far:

[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 a开发者_如何学编程s 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; 
    }
}

The reader loops twice as intended, but the return values of the second iteration are identical to the first. What should be done???


My suggestion: avoid mocking components with potentially complex (and hidden) behavior. Instead, define an adapter interface that suits your needs in a less generic way and use it in your code instead of the IDataReader. Then mock that interface, which should be a much simpler task.

In the production code, define and use an implementation of your adapter interface which works with real IDataReaders.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜