2012-08-30 58 views
3

我需要爲從數據庫加載數據的方法創建單元測試。我正在研究一些單元測試和數據庫,大多數文章告訴你應該模擬數據庫。但是,此方法基本上從數據庫加載對象,並通過SQL執行一些限制。單元測試通過nhibernate查詢數據庫

因此,我想測試的是,實際的數據庫查詢工作成功,因此我不認爲可以模擬數據庫。

我使用NHibernate作爲我的ORM,並且使用QueryOver構建查詢。由於數據庫處於不一致狀態,我發現單元測試數據庫非常成問題。任何想法/方法如何去做這樣的測試?

這是特定的方法,我想單元測試:

public IEnumerable<IArticlePanel> LoadPanelsApplicableToArticle(ArticleModule.IArticle article, Enums.ARTICLE_PANEL_LOCATION location) 
    { 
     CS.General_v3.Util.ContractsUtil.RequiresNotNullable(article, "Article must not be null"); 

     var articleList = Modules.Factories.ArticleFactory.GetAllParentsForAnArticle(article).ToList(); 
     articleList.Add(article); 

     var q = GetQuery(); 
     q = q.WhereRestrictionOn(x => x.Article).IsInG(articleList.ConvertAll<long>(x => ((IBaseDbObject)x).ID)); 
     q = q.Where(x => x.Location == location); 
     return FindAll(q); 
} 
+0

切換到sqlite數據庫進行測試。 –

回答

4

在過去,當我需要的單元測試數據庫,我通常使用SQLite。你基本上在內存中設置SQLite數據庫,然後配置你的NHibernate(依賴注入,或者你想這樣做)來連接到SQLite,而不是你的普通數據庫。幾乎所有的查詢都應該能夠正確運行。

如果您需要強大的DateTime支持,SQLite可能會讓您失望(請參閱Ayende的文章here)。在這種情況下,您可以使用任何嵌入式數據庫。我建議設置一個RAMDisk並將嵌入式數據庫放置在該磁盤上,這樣它仍然在內存中運行。

+0

這種方法的問題是有一些設置,其他值必須在數據庫中作爲特定的初始化代碼等依賴於它們。因此,我需要重新創建一個SQLite從頭開始,填充這些設置等。我試着走下這條路線,但時不時維護。 –

+0

如果您的單元測試數據庫本身確實非常重要,那麼投入一點額外時間來編寫SQLite數據庫創建和自定義代碼通常不是什麼大問題。我從來沒有遇到過要花一天多時間才能寫出初始化數據庫所需的所有內容,然後再爲所有未來的單元測試完成。如果不值得花那麼多時間,那麼根本就不值得擔心數據層的單元測試。 –

0

我個人使用真正的數據庫來做我的集成測試。我覺得這是最接近真實生產場景的。我們的開發團隊目前沒有從nhibernate映射生成數據庫,因此映射和數據庫之間存在一些不一致之處(比如數據庫默認值等)。如果您從nhibernate生成模式,SQLLite可能是您正確的路徑。但是,如果你不是,我個人覺得把這些測試與真實數據庫相比較好。

我的集成測試將爲測試插入必要的數據並在測試後刪除數據。這種方法唯一的缺陷是,您必須確保在測試結束後刪除所有數據,否則可能會影響其他測試。我發現這對我們公司來說是一個可行的解決方案,而且它非常有幫助。我們有專用的數據庫,僅用於單元測試。

下面是我的測試中的一個例子:

[TestMethod] 
public void Test_NHibernate_Query() 
{ 
    //Create the data in the database necessary to test my nhibernate query 
    CreateDataForUnitTest(); 

    IInventoryRepository target = new InventoryRepository(nhibernateSession); 

    IList<InventoryView> inventoryRecords = target.GetContainerInventory(productId); 

    Assert.AreEqual(1, inventoryRecords.Count); 
} 

[TestCleanup] 
public void CleanUp() 
{ 
    DeleteAll<Order>(); 
    DeleteAll<Company>(); 
} 

public void DeleteAll<T>() where T : Entity 
{ 
    NHibernate.ISession session = SessionFactory.GetCurrentSession(); 

    using (NHibernate.ITransaction tran = session.BeginTransaction()) 
    { 
     IList<T> items = session.CreateCriteria<T>() 
      .List<T>(); 

     foreach (T p in items) 
     { 
      session.Delete(p); 
     } 

     tran.Commit(); 
    } 
} 
+0

這就是我目前的工作方式。但是,有時由於依賴關係,清理並不容易,並使數據庫恢復到一致狀態。我希望更多地瞭解目前我是否還沒有意識到的選項,但看起來這是最適合我的案例。 –

+0

如果您使用的是mssql,如果該一致狀態表示爲空,則可能會輕鬆地將數據庫恢復爲一致狀態。 http://stackoverflow.com/questions/155246/how-do-you-truncate-all-tables-in-a-database-using-tsql我實際上可能會考慮這樣做,而不是。 –

0

我們使用IRepository從NCommon。然後我們使用InMemoryRepository進行單元測試。非常光滑,快速且易於使用。