2010-12-09 74 views
2

我使用.NET 4,NUnit和Rhino mocks。我想單元測試我的新聞庫,但我不確定如何去做。我的新聞庫是我最終將用來與數據庫進行通信的。我想用它來測試假冒僞造數據。不確定是否有可能?這是我目前有:單元測試庫需要的幫助/建議

public interface INewsRepository 
{ 
    IEnumerable<News> FindAll(); 
} 

public class NewsRepository : INewsRepository 
{ 
    private readonly INewsRepository newsRepository; 

    public NewsRepository(INewsRepository newsRepository) 
    { 
     this.newsRepository = newsRepository; 
    } 

    public IEnumerable<News> FindAll() 
    { 
     return null; 
    } 
} 

我的單元測試是這樣的:

public class NewsRepositoryTest 
{ 
    private INewsRepository newsRepository; 

    [SetUp] 
    public void Init() 
    { 
     newsRepository = MockRepository.GenerateMock<NewsRepository>(); 
    } 

    [Test] 
    public void FindAll_should_return_correct_news() 
    { 
     // Arrange 
     List<News> newsList = new List<News>(); 
     newsList.Add(new News { Id = 1, Title = "Test Title 1" }); 
     newsList.Add(new News { Id = 2, Title = "Test Title 2" }); 

     newsRepository.Stub(r => r.FindAll()).Return(newsList); 

     // Act 
     var actual = newsRepository.FindAll(); 

     // Assert 
     Assert.AreEqual(2, actual.Count()); 
    } 
} 

在上面的代碼,我不知道我需要模擬。上面的代碼編譯但在NUnit GUI中關於構造器值失敗。我只能假設它與我需要提供給NewsRepository的INewsRepository參數有關。我不知道如何在測試中做到這一點。有人可以糾正我的單元測試,以便它會通過NUnit GUI?某人是否也可以提供一些關於我是否正確實施存儲庫的反饋?

作爲一個新手嘲笑,有什麼我需要驗證?我什麼時候需要驗證?它的目的是什麼?我一直在努力完成一些源代碼項目,一些使用驗證,一些則不使用。

如果上述測試通過,這對開發者證明了什麼?另一個開發人員必須對我的存儲庫做些什麼才能使其在NUnit GUI中失敗?

對不起,所有的問題,但他們是新手問題:)

我希望soomeone能幫助我。

+0

我看到對不對? NewsRepository本身具有相同的功能? – Aliostad 2010-12-09 13:36:29

+0

@Aliostad:你是什麼意思? – 2010-12-09 13:39:15

回答

5

正如史蒂文所說,你在Assert對上述代碼中的Mock NewsRepository。

嘲諷的想法是隔離被測代碼並且創建假貨以取代他們的依賴

您使用模擬NewsRepository測試的東西,使用INewsRepository,你的情況,你提到NewsService; NewsService將使用你的模擬INewsRepository

如果您在解決方案中搜索使用INewsRepository.FindAll()的任何內容,您將創建一個模擬存儲庫以單獨測試該代碼。

如果你想測試一些調用你的服務層的東西,你將需要模擬NewsService

而且,史蒂芬的說,沒有必要爲NewsRepository有由國際奧委會注入其自身的副本,所以:

public class NewsRepository : INewsRepository 
{ 
    private readonly INewsRepository newsRepository; 

    public NewsRepository(INewsRepository newsRepository) 
    { 
     this.newsRepository = newsRepository; 
    } 

    public IEnumerable<News> FindAll() 
    { 
     return null; 
    } 
} 

應該變成:

public class NewsRepository : INewsRepository 
{ 
    public IEnumerable<News> FindAll() 
    { 
     return null; 
    } 
} 

一旦你有功能在您需要測試的FindAll()方法中,您可以模擬他們使用的對象

作爲一個偉大的風格點Art Of Unit Testing模擬對象的初始化最好從Setup方法中排除,並在方法開始時調用的輔助方法中執行。由於安裝程序的調用將不可見,並使模擬的初始化不清晰。

作爲另一個風格點,從這本書中,建議的單元測試命名約定是:「MethodUnderTest_Scenario_ExpectedBehavior」。 所以,

FindAll_should_return_correct_news
可能成爲,例如:
FindAll_AfterAddingTwoNewsItems_ReturnsACollectionWithCountOf2

我希望這使得該方法更清晰。

2

您的FindAll_should_return_correct_news測試方法未測試存儲庫,它正在測試自身。你可以看到這個當你把它簡化一下它確實:

[Test] 
public void FindAll_should_return_correct_news() 
{ 
    // Arrange 
    List<News> newsList = new List<News>(); 
    newsList.Add(new News { Id = 1, Title = "Test Title 1" }); 
    newsList.Add(new News { Id = 2, Title = "Test Title 2" }); 

    // Act 
    var actual = newsList; 

    // Assert 
    Assert.AreEqual(2, actual.Count()); 
} 

正如你所看到的,有什麼你基本上做的是創建一個列表,加油吧和測試,如果它實際上包含的記錄數你把它放進去。

當您的存儲庫除了數據庫交互(沒有應用程序邏輯)什麼也不做,沒有什麼可以使用單元測試進行測試。你可以通過編寫集成測試來解決這個問題。你基本上可以用這樣一個集成測試做什麼,就是在測試數據庫中插入一些記錄(儘管使用真實的數據庫,而不是內存數據庫),然後調用真實的存儲庫類來查看它是否從測試中獲取預期記錄數據庫。所有應該在事務中執行並在測試結束時回滾(這確保了這些測試值得信賴)。

當您使用允許編寫LINQ查詢的O/RM工具時,您也可以嘗試不同的方法。您可以僞造您的LINQ提供商,如您在this article中看到的那樣。