2011-05-24 55 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