2008-11-02 50 views
5

我完全是C#和NUnit的新手。NUnit的ExpectedExceptionAttribute是測試是否引發異常的唯一方法嗎?

在Boost.Test中有一個BOOST_*_THROW宏的家族。在Python的測試模塊中有TestCase.assertRaises方法。

據我所知,在NUnit(2.4.8)的C#中,唯一的異常測試方法是使用ExpectedExceptionAttribute

爲什麼我更喜歡ExpectedExceptionAttribute - 比如說 - Boost.Test的方法?這個設計決定背後有什麼推理?爲什麼在C#和NUnit的情況下更好?

最後,如果我決定使用ExpectedExceptionAttribute,那麼在異常被引發和捕獲之後,如何做一些額外的測試?假設我想測試要求,在某個setter提出System.IndexOutOfRangeException之後對象必須是有效的。你如何解決下面的代碼來編譯和按預期工作?

[Test] 
public void TestSetterException() 
{ 
    Sth.SomeClass obj = new SomeClass(); 

    // Following statement won't compile. 
    Assert.Raises("System.IndexOutOfRangeException", 
        obj.SetValueAt(-1, "foo")); 

    Assert.IsTrue(obj.IsValid()); 
} 

編輯:謝謝您的回答。今天,我發現了一個這是測試blog entry其中提到你所描述的所有三種方法(和一個更小的變化)。這是恥辱,我不能:-(之前找到它

回答

13

我很驚訝,我還沒有看到提到這個模式。大衛·阿諾的是非常相似的,但我更喜歡這樣的簡單:

try 
{ 
    obj.SetValueAt(-1, "foo"); 
    Assert.Fail("Expected exception"); 
} 
catch (IndexOutOfRangeException) 
{ 
    // Expected 
} 
Assert.IsTrue(obj.IsValid()); 
10

如果你可以使用NUnit的2.5有一些不錯的helpers

Assert.That(delegate { ... }, Throws.Exception<ArgumentException>()) 
+1

+1。我更喜歡使用這種風格,因爲編寫測試所需的儀式較少,尤其是如果您需要保留對檢查消息等的引用。您還可以使用var exception = Assert.Throws (()=> myInstance.DoSomethingInvalid( )); – 2010-06-27 02:35:30

2

我一直採取以下方法:。

bool success = true; 
try { 
    obj.SetValueAt(-1, "foo"); 
} catch() { 
    success = false; 
} 

assert.IsFalse(success); 

... 
+0

就我個人而言,我會捕獲一個特定的異常,但這將起作用; -p – 2008-11-03 04:58:19

+0

@Marc,有效的觀點:它應該捕獲測試中的特定異常並讓其他人通過,以使它們顯示爲錯誤而不是測試失敗。 – 2008-11-03 08:43:54

4

MbUnit的語法是

Assert.Throws<IndexOutOfRangeException>(delegate { 
    int[] nums = new int[] { 0, 1, 2 }; 
    nums[3] = 3; 
}); 
2

您的首選語法:

Assert.Raises("System.IndexOutOfRangeException", 
       obj.SetValueAt(-1, "foo")); 

與C#woiuldn't工作無論如何 - 在obj.SetValueAt會進行評估,並將結果傳遞給Assert.Raises。如果SetValue拋出一個異常,那麼你永遠不會進入Assert.Raises。

你可以寫一個輔助方法來做到這一點:

void Raises<T>(Action action) where T:Exception { 
    try { 
     action(); 
     throw new ExpectedException(typeof(T)); 
    catch (Exception ex) { 
     if (ex.GetType() != typeof(T)) { 
     throw; 
     } 
    } 
} 

它允許類似的語法:

Assert.Raises<System.IndexOutOfRangeException>(() => 
    obj.SetValueAt(-1, "foo") 
;