2011-05-24 61 views
2

我想用RhinoMocks模拟IDataReader,但是我很难使其遍历DataRows。以下是我迄今所做的:无法让RhinoMock迭代通过DataReader

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

读者两次循环如预期,但第二次迭代的返回值是相同的第一。应该做什么???

+0

您是否验证了'CallBackDelegate'在正确的时间被调用,并且'currentRowIdx'变量正在增加? – 2011-05-24 09:13:25

+0

@Enrico,时间是正确的,currentRowIdx表现很好:o) – Morten 2011-05-24 09:50:23

回答

3

我的建议:避免嘲笑具有潜在复杂(和隐藏)行为的组件。相反,请定义一个适合您需求的适配器接口,但不要使用IDataReader,而是在您的代码中使用它。然后嘲笑那个接口,这应该是一个更简单的任务。

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

+0

@Igor,我想到了这些方面,但我还没准备好接受它。如果我能找到解决方案,我可以在很多情况下使用它。 – Morten 2011-05-24 10:55:18

+1

@Morten,如果你坚持嘲笑它,我建议实现你自己的'DummyDataReader'而不是使用Rhino来模拟。 Rhino对于简单的场景很有用,但是如果你需要一个可重用的虚拟组件,那么实现它而不是设置模拟是一个更好的选择。 – 2011-05-24 18:19:43

+0

@Igor,我认为你是对的。我刚开始深入挖掘Rhino Mocks更先进的功能,并希望从中获得一些真正的价值。我想我已经达到了极限。感谢您的反馈:o) – Morten 2011-05-24 18:44:33