2013-11-24 92 views
2

在編寫單元測試時,我們總是說我們需要確保代碼始終與外部依賴關係隔離。 Moq之下已被用來提供一個模擬對象,而不是一個有效的流利的nhibernate會話工廠。單元測試 - 從外部依賴關係的隔離

public class and_saving_a_invalid_item_type : 
    when_working_with_the_item_type_repository 
    { 
    private Exception _result; 
    protected override void Establish_context() 
    { 
     base.Establish_context(); 
    _sessionFactory = new Mock<ISessionFactory>(); 
     _session = new Mock<ISession>(); 

     _sessionFactory.Setup(sf => sf.OpenSession()).Returns(_session.Object);   
     _itemTypeRepository = new ItemTypeRepository(_sessionFactory.Object); 

     _session.Setup(s => s.Save(null)).Throws(new ArgumentNullException()); 
    } 
    protected override void Because_of() 
    { 
     try 
     { 
      _itemTypeRepository.Save(null); 
     } 
     catch (Exception ex) 
     { 

      _result = ex; 
     } 

    } 

    [Test] 
    public void then_an_argument_null_exception_should_be_raised() 
    { 
     _result.ShouldBeInstanceOfType(typeof(ArgumentNullException)); 
    } 
} 

實際執行情況如下所示。測試運行良好。但是如果沒有設置拋出argumentnullexception的期望,save方法實際上會返回NullReferenceException。重點是:不是單元測試掩蓋了實際結果。雖然要求是從單元測試的角度來實現的,但它在實施時並未實現。

public class ItemTypeRepository : IItemTypeRepository 
{ 
public int Save(ItemType itemType) 
    { 
     int id; 
     using (var session = _sessionFactory.OpenSession()) 
     { 
      id = (int) session.Save(itemType);     
      session.Flush(); 
     } 
     return id; 
    } 
} 

回答

2

你是對的 ,因爲它是唯一的NHibernate的是被在這個示例中進行測試,並 (編輯:NHibernate的也不測試),測試並沒有做太多。即使查詢很複雜,大多數人都選擇針對內存數據庫(或真實數據庫)編寫集成測試,因爲它會測試相同的路徑,並且無論如何都會寫入。與集成測試相比,嘲笑數據庫通常不會帶來投資回報。

這些鏈接還可以幫助:

更新:該庫中的例子肯定在生活中的一些目的,例如它會本類使用:

class ItemUser { 
    public ItemUser(IItemRepository repository) {} 
} 

我的觀點是:測試ItemUser與moq實例IItemRepository更有成效。項目是否真的保存將在集成測試中進行測試。

+0

然後,如果最終我們需要編寫集成測試,那麼通過使用模擬框架進行隔離的單元測試的目的是什麼? – arjun

+0

你可以在不嘲笑ISessionFactory的情況下嘲笑版本庫;例如:只是測試邏輯,假裝項目被保存在存儲庫中;這就是集成測試中要測試的內容。請參閱更新。 – henginy

2

這個測試沒有什麼意義,因爲你基本上只是在測試模擬返回一個異常。你沒有測試nhibernate,因此測試沒有實際價值。

唯一的單元測試這將使意義正在測試session.Save(itemType)被稱爲不管你傳遞和session.Flush();被稱爲事後! 這將驗證這部分代碼始終在做着這些...

單元測試業務邏輯和集成測試數據訪問之間存在一些根本差異。

你的例子是一個典型的數據訪問類。你實際上只是用你自己的Save方法來包裝一些nhibernate邏輯......

爲了測試nhibernate自己的行爲,你必須對某種數據庫進行集成測試,而不要嘲笑nhibernate。

無論如何,關於您發佈的代碼的一件小事。您應該實際檢查null,因爲該方法是公開的,並且您希望某些值不爲null。不要讓nhibernate以後失敗。只需做一個空檢查。並且單元測試那個。