2013-10-12 94 views
0

我對80%簡單邏輯和20%複雜邏輯的項目進行TDD。如果證明方法拋出錯誤並且懷疑正確的方法,我發現自己測試了很多。我使用NUnit和JustMock。測試異常的正確方法

我有兩種方法來做到這一點。使用ExpectedException屬性並分類類型。或者寫下如下。寫如下的專業版,我也可以斷言exception.message(如果我做了一個自定義的),並且如果測試失敗,我也會顯示exception.message。但我想與他人覈對你是如何做到的。所以總結一下:

  1. 對這樣的例外進行大量測試是否正常?
  2. 這是做正確的方式:

只是解釋:一個供應商提供某些合同,一處接受一個合同,但不能有同一個供應商一個以上的合同(但五言可以有不同的供應商不同的合同)

[Test] 
    public void Accepting_more_than_one_contract_from_supplier_throws_exception() 
    { 
     //Arrange 
     var department = new Department(Guid.NewGuid(), "1234"); 
     var supplier = Mock.Create<Supplier>(); 
     var contract1 = Mock.Create<DeliveryContract>(); 
     var contract2 = Mock.Create<DeliveryContract>(); 
     var id = Guid.NewGuid(); 
     supplier.Arrange(x => x.Id).Returns(id); 
     contract1.Arrange(x => x.Supplier).Returns(supplier); 
     contract2.Arrange(x => x.Supplier).Returns(supplier); 

     //Act 
     department.AcceptContract(contract1); 

     //Assert 
     try 
     { 
      department.AcceptContract(contract2); 
      Assert.Fail("Duplicate contract with supplier did not throw an exception"); 
     } 
     catch (Exception ex) 
     { 
      Assert.AreEqual(typeof(ArgumentException),ex.GetType(),ex.Message); 
     } 
    } 

回答

6

您可以使用Assert.Throws方法:

Assert.Throws<ArgumentException>(() => department.AcceptContract(contract2)); 

Assert.Throws<ArgumentException>(() => department.AcceptContract(contract2), "some message"); 
+0

這是一個更好的辦法來做到這一點比上面? – cfs

+0

是的,它在NUnit中定義。你不覺得它比try-catch塊更好嗎? –

+0

是的,我確實這麼認爲,但ExceptionAttribute也是這樣;)但我認爲try/catch塊確實顯示了測試的內涵,以及它應該如何工作。此外,還可以斷言異常消息,這更加獨特。在聲明錯誤的爭論性錯誤時有一些問題,例如,如果我在另一個字段中檢查空字符串,並拋出一個ArgumentException,並且測試通過了錯誤的條件。 – cfs

2

正如@Ufuk說。使用Assert.Throws<T>其中T是一種例外類型。

如果你還需要檢查異常消息使用這一個:

T Assert.Throws<T>(TestDelegate code, string message); 
T Assert.Throws<T>(TestDelegate code, string message, 
     params object[] parms); 

順便說一句,你的測試創建不應該嘲笑,但存根數據。 通過存根我的意思是隻包含測試數據的對象,在你的情況下,你提供對象的行爲 - 而不是數據。

我建議你使用NBuilder code.google.com/p/nbuilder/。您可以通過它創建清楚的存根。它也具有很大的創建對象的靈活性,可以隨機或準確地爲您的測試用例創建它們。

的使用你的情況:

var supplierStub = Builder<Supplier> 
       .With(supplier => supplier.Id = id) 
       .Build(); 

var contractsStub = Builder<DeliveryContract>.CreateListOfSize(2) 
       .All() 
        .With(contract => contract.Supplier = supplierStub) 
       .Build(); 

+0

感謝您對NBuilder的建議。只有一個問題,你發現自己做了很多這樣的測試,還是測試這樣的例外的代碼是錯誤的? – cfs

+1

它依賴於類邏輯流程。在你的例子中拋出異常並不明顯,它是類邏輯的一部分,所以測試它是合理的。請記住,測試可能是您的代碼的良好文檔。 我正在測試大多數情況下,當我把它們直接拋出代碼(通過throw)或程序在某些情況下拋出異常的異常代碼。 對我來說,很好的例子是測試servis負責閱讀.xml文件f.e.由LinqToXml。要測試的好例子是如果一個節點缺失,服務將如何運作。 – michalczukm