2010-02-11 42 views
30

我正在創建一個公開IQueryable的存儲庫。嘲笑我的單元測試的最好方法是什麼?我如何模擬IQueryable <T>

由於我使用RhinoMocks爲我的模擬對象的其餘部分,我試圖做到以下幾點:

IQueryable<MyObject> QueryObject = 
    MockRepository.GenerateStub<IQueryable<MyObject>>(); 

這不,雖然,所以我試着這樣做的工作:

IQueryable<MyObject> QueryObject = 
    (new List<MyObject> { new MyObject() }).AsQueryable(); 

有沒有更好的方法來做到這一點,或有任何其他模擬框架建立在IQueryable的支持?

我的倉庫界面看起來是這樣的:

public interface IRepository<T> where T : TableServiceEntity 
{ 
    IQueryable<T> Table { get; } 
    void Attach(T existingItem); 
    void Delete(T itemToDelete); 
    void Insert(T newItem); 
    T Load(string partitionKey, string rowKey); 
    IEnumerable<T> Load(string partitionKey); 
    IEnumerable<T> Query(IQueryable<T> query); 
    IEnumerable<T> Last(int count); 
    T Last(); 
    void Update(T item); 
} 

這裏是我要測試的方法:

public Post LoadPost(int year, int month, int day, string slug) 
{ 
    var query = from p in _blogRepository.Table 
       where 
        p.PartitionKey == Key.Partition(year, month, day) 
        && p.Slug == slug 
       select p; 

    var posts = _blogRepository.Query(query.Take(1)); 

    return posts.First(); 
} 

那麼這裏就是測試,因爲我有它現在將測試LoadPost 。

[Fact] 
public void LoadWillRetrieveByPartitionKeyAndRowKeyWhenUsingUriFormat() 
{ 
    Repository 
     .Stub(x => x.Query(Arg<IQueryable<Post>>.Is.Anything)) 
     .Return(new List<Post> {_post}); 

    var result = Service.LoadPost(
          _post.Year(), 
          _post.Month(), 
          _post.Day(), 
          _post.Slug); 

    Assert.NotNull(result); 
} 

該代碼取自我的AzureBlog項目。

+0

你能粘貼你的測試嗎? – Grzenio 2010-02-11 14:43:26

回答

8

我平時做你最後正是在您的測試做。在編寫我的測試時,我假定.Net庫類能夠正常工作,並且不包含錯誤,所以我可以在測試中使用它們。當我需要測試列表,集合,查詢,字典等時,我只是創建真實的東西並填充測試數據。它使測試更加可讀和更快寫入,說實話,風險是不存在的。

3

如果你想嘲笑你的倉庫,你不會嘲笑IQueryable。相反,嘲笑你的倉庫的方法來返回可用於運行你的單元測試的固定的,已知的值(如你的第二個例子)。

+0

我已經開始沿着這條路線走下去,然後通過一個通用的存儲庫創建一個特定存儲庫的額外層。這導致我的域服務 - >域存儲庫 - >通用存儲庫。如果我能夠從域服務 - >通用存儲庫,並仍然可以測試沒有實現細節泄漏到域服務我會更加快樂,因爲它是需要維護和測試的代碼少。 – 2010-02-12 04:36:21

+0

我明白你的意思了。但是,如果你的問題是爲你的DomainService編寫單元測試而產生的,那麼我認爲你應該模仿DomainRepository並且不必擔心Generic Repository(現在)。單元測試DomainService最好通過嘲弄它的依賴性來完成。就DomainService而言,它不應該關心DomainRepository如何實現(即從基類繼承)。希望這可以幫助! – PatrickSteele 2010-02-12 18:13:21

0

我不確定這是否會幫助你...但我做了類似你所說的事情。在我的場景中,我有一個使用存儲庫的數據上下文類。

我開始創建一個包含IQueryable方法的接口(IRepository)。然後我創建了兩個實現此接口的類。一個類使用ORM進行數據操作(DbEntityRepository),另一個類使用類屬性(MemoryRepository)。數據上下文類有一個需要IRepository的構造函數。這樣做可以在測試數據上下文時使用MemoryRepository,並且可以爲應用程序使用DbEntityRepository。

如果你有興趣......你可以找到在CodePlex上的代碼:IQToolkitContrib

2

我知道這是一個老問題,但只是想補充我的2美分。

我與使用SharpLite生成的存儲庫有相同的問題,這是我不時使用的ASP .NET MVC框架。過了一段時間,我發現了一個解決方案,唯一的問題是使用Moq,而不是Rhino Mocks,但是可能你可以找到適應它的方法。我做了一個blog post here如何做到這一點。

它基本上創建一個實現IQueryable的列表並將其用作假數據背景。希望我能幫助!

相關問題