无法让 RhinoMock 迭代 DataReader

发布于 2024-11-09 19:25:33 字数 3766 浏览 0 评论 0原文

我正在尝试使用 RhinoMocks 模拟 IDataReader,但我很难让它迭代 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; 
    }
}

读取器按预期循环两次,但第二次迭代的返回值与第一次相同。应该怎么办???

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

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

懒的傷心 2024-11-16 19:25:33

我的建议:避免模拟具有潜在复杂(和隐藏)行为的组件。相反,以不太通用的方式定义一个适合您需求的适配器接口,并在代码中使用它而不是 IDataReader。然后模拟该接口,这应该是一个简单得多的任务。

在生产代码中,定义并使用与真实的 IDataReader 一起使用的适配器接口的实现。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文