2010-08-26 70 views
6

我在我的數據訪問層中執行映射的方法。該方法接受DataReader,並將數據映射到適當的域對象屬性。有沒有一種很好的方式來模擬DataReader,這樣我就可以對映射方法執行單元測試而不會碰撞物理數據庫?如何將DataReader模擬爲單元測試DAL

回答

11

幸運的是,DataReader實現了IDataReader接口。

代替依靠代碼中的DataReader,請使用IDataReader。然後,在您的測試中,您可以替換您自己的實現來返回虛擬數據,或使用模擬框架(如Rhino.Mocks或類似)來創建存根並分配返回值。

根據你在代碼中「獲得」DataReader的方式,你可能需要做一些重構。你想要的是在構造函數(首選)或通過屬性中「注入」這樣的外部依賴項,以便該類的消費者可以替換IDataReader的任何實現。 (這種替換也是爲什麼你聲明你的參數/屬性爲抽象而不是具體類型。)這被稱爲Dependency Injection,一種形式Inversion of Control

3

如果您想模擬IDataReader返回記錄列表,您可以創建一個實現IDataReader並覆蓋其一些方法(如Read()和Indexer)的類。另外,您需要一個變量來保存當前行的記錄和保存列表值的變量。下面是這樣做的示例代碼:

public class MockDataReader : IDataReader 
{ 
    private int _rowCounter = 0; 
    private List<Dictionary<string,object>> _records = new List<Dictionary<string,object>>(); 

    public MockDataReader(List<Dictionary<string,object>> records) 
    { 
     _records = records; 
    } 

    public bool Read() 
    { 
     _rowCounter++; 
     if (_rowCounter < _records.Count) return true; 
     return false; 
    } 

    public object this[string name] 
    { 
     get { return _records[_rowCounter][name]; } 
    } 
} 

然後利用這一類的,你可以使用下面的代碼:

var itemsList = new List<Dictionary<string, object>>(); 
for (int i = 0; i < 5; i++) 
{ 
    var num = i + 1; 
    var items = new Dictionary<string, object>(); 
    items.Add("Id", num); 
    items.Add("FirstName", "MyFirstName" + num); 
    items.Add("LastName", "MyLastName" + num); 
    itemsList.Add(items); 
} 


var result = new MockDataReader(itemsList); 

不是一個完整的證明方式,但工程。希望它有助於:)

+0

我不會創建實際的類來模擬'IDataReader',而是+1來顯示你需要設置你的模擬對象來實現。 – krillgar 2015-10-23 17:58:45