2015-05-21 21 views
2

我有一個項目,我用這個方法將它添加到數據庫:我該如何測試一種方法將項目添加到數據庫?

public Messages addItem(Item item) 
{ 

    Messages resultMessage = Messages.Success; 

    using (IUnitOfWork unitOfWork = new UnitOfWork()) 
    { 
     IItemRepository itemRep = new ItemRepository(unitOfWork); 

     try 
     { 
      itemRep.Insert(item); 

      unitOfWork.Commit(); 
     } 
     catch (Exception e) 
     { 
      Console.WriteLine(e.StackTrace); 
      resultMessage = Messages.DB_Failure; 
     } 
    }  
    return resultMessage; 
} 

現在我必須做出編寫單元測試此方法來檢查,如果該項目被添加到數據庫中。我不知道我該怎麼做,有人可以幫我嗎?

+0

看看[測試](https://msdn.microsoft.com/en-us/library/jj159345.aspx)。您是否正在爲該項目編寫一個單元測試? – lloyd

+2

通常,當人們談論單元測試時,他們正在討論如何測試類的行爲而不會觸及數據庫之類的東西。爲了進行測試,他們通常會模擬出諸如存儲庫之類的東西。如果你真的想讓你的測試寫入數據庫,這通常被稱爲集成測試。你真的感興趣的是哪一個? – forsvarir

回答

4

您的代碼與ItemRepository和UnitOfWork實現結合在一起。理想情況下,你應該解耦他們,並使用mock來驗證正確的方法被調用。

一個可能的解決方案:

  1. 使存儲庫工作
  2. 的單元上的屬性,則不要直接創建工作單元,使用工廠爲
  3. 使工廠的依賴你的班級
  4. 在你的測試中,將工廠模擬傳給正在測試的班級,返回工作單元的模擬
  5. 返回你的UoW模擬庫上的模擬
  6. 驗證正確的方法被調用你的庫模擬和工作單元嘲笑

這將是一個例子。我用Moq作爲模擬框架。並把測試方法的類裏面,但你可以得到的想法:

class MyClass 
{ 
    private readonly IUnitOfWorkFactory _factory; 

    public MyClass(IUnitOfWorkFactory factory) 
    { 
     _factory = factory; 
    } 

    public Messages addItem(Item item) 
    { 
     Messages resultMessage = Messages.Success; 

     using (IUnitOfWork unitOfWork = _factory.GetUnitOfWork()) 
     { 
      try 
      { 
       unitOfWork.ItemRep.Insert(item); 

       unitOfWork.Commit(); 
      } 

      catch (Exception e) 
      { 
       Console.WriteLine(e.StackTrace); 
       resultMessage = Messages.DB_Failure; 
      } 


     } 

     return resultMessage; 
    } 


    public void Test() 
    { 
     // Arrange 
     var factoryMock = new Mock<IUnitOfWorkFactory>(); 
     var uowMock = new Mock<IUnitOfWork>(); 
     var repositoryMock = new Mock<IItemRepository>(); 

     factoryMock.Setup(f => f.GetUnitOfWork()).Returns(uowMock.Object); 
     uowMock.Setup(u => u.ItemRep).Returns(repositoryMock.Object); 

     var sut = new MyClass(factoryMock.Object); 

     // Act 
     var item = new Item(); 
     sut.addItem(item); 


     // Assert 
     repositoryMock.Verify(r => r.Insert(item), Times.Once); 
     uowMock.Verify(u => u.Commit(), Times.Once); 
    } 
} 
+0

我的想法非常清楚,謝謝你的例子 – dtmnn

+1

如何檢索數據?你不需要嘲笑回購中的功能嗎?假設你調用addItem()五次。然後你調用一個函數'getInventory()'並返回一個ViewModel,它帶有'IEnumerable '類型的'Items'屬性。你會如何測試? – Gaui

+0

您如何測試被測試的方法沒有做更多的事情?可能是在添加之前調用Save(),而不是之後,這將是一個錯誤。還是超出了單元測試本身的範圍? –

0

正如你現在的方法,它不能被單元測試,因爲它是硬編碼寫入數據庫的。

傳統的解決方法是將IItemRepository的實例傳遞給方法,而不是讓方法創建它。這樣做,然後你可以自由地創建一個模擬的IItemRepository實現,可以報告正在寫入數據庫的內容。

0

至於其他答案建議:儘量類測試從難/慢分開來測試像數據庫的依賴。您可以使用多種方法來實現此結果,但它們都達到了相同的效果: 不要創建(新增)依賴項,這會使您想要自行測試的代碼中的單元測試變得困難(比如您的unitofwork/repository )。相反,問外部世界的這些依賴關係(谷歌依賴倒置/ DI的進一步信息)。

如果你想用真實數據庫測試版本庫的實現,我建議你通過你的版本庫的公共API進行測試。不要去編寫「SELECT * FROM Items」查詢自己,但使用repository.GetItem(...)方法(如果可用)。這樣你的測試就不那麼脆弱了,並且與你的存儲庫類的實際實現無關。

0

你說目標是「檢查這個項目是否被添加到數據庫」。

這是你通常不會寫單元測試的原因,因爲它是數據庫的責任,這可能是你不是那個開發者。

單元測試的一個更好的情況是嘲笑數據庫並檢查決定將某些內容添加到數據庫的邏輯。例如:

  1. 工作單元由客戶/操作員描述。
  2. 您的組件查詢數據庫中是否存在該項目。
  3. 沒有相應的項目存在。
  4. 您的組件將項目添加到數據庫。

這是通過僅使用數據庫模擬實現的,它正在測試您的代碼而不是數據庫。

相關問題