2012-04-24 158 views
4

我已經寫了使用資源庫使用RavenDB提到在以下博客-後 (http://www.codecapers.com/post/Using-RavenDB-with-ASPNET-MVC.aspx)以下方法:IRepository如何進行單元測試?

public User GetUserById(string id) 
{ 
    var user = (from usr in _repository.All<User>() where usr.Id == id select usr).FirstOrDefault(); 

    if (user == null) 
    { 
      throw new NullReferenceException("No user with the id (" + id + ") could be found."); 
    } 

    return user; 
} 

你將如何單元測試這種方法與NUnit的(也許MOQ)?

「用戶」只是一個普通的類。

回答

0

的第一個問題將是 - 什麼是你在這方面的測試?提供的方法確實只有兩個結果,所以基本上測試user是否爲空。這是一個增值測試嗎?

至於如何,林假設_repository通過某種機制注入?如果是這樣,那麼只需提供一個Mock<IRepository>(根據需要插入您的類型名稱),然後在注入的地方注入_repository。然後,您可以設置返回值並測試您的方法是否存在異常。

mockRepository.Setup(x => x.All<User>()).Returns(new List<User> { ... }); 
+1

否:您還在測試您的方法是否會返回正確的用戶。沒有什麼可以保證'GetUserById(「4」)'返回一個ID爲「4」的用戶,除非你明確地測試它。假設我只從庫中返回數據,假設有10個'Users'的存儲庫,那麼有11個可能的結果*。所以,如果你正在進行徹底的測試,還有很多東西需要測試。 – 2012-04-24 14:58:44

2

Usualy你不直接對存儲庫層寫測試。 說例如你正在使用nHibernate或實體框架,而不是對知識庫進行測試,從技術上講,測試該框架。

創作者或那些ORMs已經完成了。

與數據庫交談也會讓您的測試成爲集成測試而不是單元測試。

單元測試將是例如對業務層嘲諷出庫層。

如果你想要寫一個集成測試還編寫針對業務層,但不嘲笑庫層,讓它通過。

+0

這不是關於測試存儲庫層。它正在測試GetUserById方法的邏輯是正確的,它可能不是。您可以信任正確的倉庫實施,但這並不意味着您的代碼使用正確! – 2012-04-24 14:54:53

+0

我只提到它,道歉,如果這使我的答案不清楚。我假設GetUserById是業務層中的一種方法,因此如果您想檢查方法返回的是正確的數據,則可以針對它編寫集成測試。在您的測試中,您首先將測試數據插入數據庫,然後執行您的方法,然後聲明期望值由調用返回。如果你編寫一個單元測試,你只需簡單地模擬庫層,並在模擬對象中設置GetUserById的期望值,以確保它被調用。 – Nope 2012-04-24 15:20:20

1

我會做以下準備代碼:

  1. 確保您_repository被傳遞通過構造函數或屬性,以便它可以很容易地改變了測試。
  2. 確保您_repository變量聲明爲IRepository類型,而不是具體類型。

然後,在你的測試:

  1. 創建界面的模擬,並通過這是你的_repository
  2. 重寫.All<User>()方法返回的User一個已知的,硬編碼列表與你的測試合適的值。
  3. 斷言在一次測試中查詢現有ID時返回正確的值。
  4. 斷言在單獨的測試中,當您查詢不存在的ID時引發異常。
0

RavenDB是專門設計,讓你需要模擬家居單元測試。

只需在內存中運行它,然後就可以直接對它執行單元測試。有關更多信息,請參閱this blog post

它可以讓你寫這樣的代碼:

[Fact] 
public void CanQueryForDistinctItemsUsingLinq() 
{ 
    using (var store = NewDocumentStore()) 
    { 
     using (var s = store.OpenSession()) 
     { 
      s.Store(new { Name = "ayende" }); 
      s.Store(new { Name = "ayende" }); 
      s.Store(new { Name = "rahien" }); 
      s.SaveChanges(); 
     } 

     store.DocumentDatabase.PutIndex("test", new IndexDefinition 
     { 
      Map = "from doc in docs select new { doc.Name }", 
      Stores = { { "Name", FieldStorage.Yes } } 
     }); 

     using (var s = store.OpenSession()) 
     { 
      var objects = s.Query<User>("test") 
       .Customize(x => x.WaitForNonStaleResults()) 
       .Select(o => new {o.Name }) 
       .Distinct() 
       .ToList(); 

      Assert.Equal(2, objects.Count); 
      Assert.Equal("ayende", objects[0].Name); 
      Assert.Equal("rahien", objects[1].Name); 
     } 
    } 
} 

這個來自RavenDB unit/integration tests,所以你需要一些infasctucture得到它的工作,但它給人的總體思路。

+0

是的,但是當你可以寫一個實際測試整個事物(控制器,數據庫等)的集成測試時,爲什麼還要設置模擬,期望等來編寫單元測試呢? – 2012-04-24 20:20:47

+0

不確定在內存中是否意味着raven只是在內存中運行一個虛假的數據庫。單元測試應該模擬所有的外部層,但是當你將數據寫入數據庫,內存或其他數據存儲時,我會認爲這不是單元測試,而是集成測試。 – Nope 2012-04-24 20:21:38

+0

@FrançoisWahl看看Ayende的一些博客文章,可以給出比我更好的解釋。請參閱http://ayende.com/blog/153029/northwind-starter-kit-review-data-access-and-the-essence-of-needless-work-part-ii?key=01a97aa23ec049839c3fb2dd91421e61和http:// ayende對於初學者來說,他們是值得的生活(這個系列還有其他人) – 2012-04-24 20:24:56

相關問題