2013-06-05 114 views
12

上面的代碼塊指的是另一個問題+在SO上的答案不包含這裏適用的正確答案!catch是否支持泛型異常?

我有一個用於單元測試的方法。此方法的目的是確保一段代碼(由委託人引用)會拋出特定的異常。如果拋出異常,則單元測試成功。如果沒有引發異常或引發其他類型異常,則單元測試將失敗。

/// <summary> 
/// Checks to make sure that the action throws a exception of type TException. 
/// </summary> 
/// <typeparam name="TException">The type of exception expected.</typeparam> 
/// <param name="action">The code to execute which is expected to generate the exception.</param> 
public static void Throws<TException>(Action action) 
    where TException : Exception 
{ 
    try 
    { 
     action(); 
    } 
    catch (TException) 
    { 
     return; 
    } 
    catch (Exception ex) 
    { 
     Assert.Fail("Wrong exception was thrown. Exception of type " + ex.GetType() + " was thrown, exception of type " + typeof(TException) + " was expected."); 
    } 
    Assert.Fail("No exception was thrown. Exception of type " + typeof(TException) + " was expected."); 
} 

下一次調用應該會成功,但它失敗:

int result = 0; 
Throws<DivideByZeroException>(() => result = result/result); 

TException型的預期異常被拋出,它總是由第二catch捕獲,而不是由第一擋。爲什麼是這樣?

當然,如果ex的類型爲TException,我可以使用workarround一個catch。我只是想知道/理解爲什麼這個代碼編譯但簡單(從不?)的作品。

編輯

在請求中的 「工作」 演示:

using System; 

namespace GenericExceptionDemo 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      int n = 0; 
      Catch<DivideByZeroException>(() => n = n/n); 
     } 

     static public void Catch<TException>(Action action) 
      where TException: Exception 
     { 
      try 
      { 
       action(); 
       Console.WriteLine("No exception thrown. !!!Fail!!!"); 
      } 
      catch (TException) 
      { 
       Console.WriteLine("Expected exception thrown. PASS!"); 
      } 
      catch(Exception ex) 
      { 
       Console.WriteLine("An unexpected exception of type " + ex.GetType() + " thrown. !!!FAIL!!!"); 
      } 
     } 
    } 
} 
+7

你使用什麼單元測試框架?大多數已經有'Assert.Throws' ... –

+8

您的代碼適合我...請顯示一個簡短但完整的程序來演示問題。 –

+0

爲什麼要聲明拋出異常類型的異常?當你使用圖形用戶界面時,.Net框架本身會引發你一個System.Drawing.Exception? –

回答

2

你不是遇到這個問題的第一人。 This question非常相似。如果您深入瞭解答案和鏈接,那麼就會涉及到CLR中的一個錯誤。

編輯: 作爲後續行動,我已經運行馬丁的從VS2010例子,得到了以下結果:

  • 打靶.NET 4,PASS
  • 打靶.NET 3.5,FAIL
  • 在RELEASE模式下將.NET 3.5作爲目標,PASS

不幸的是,所有到微軟錯誤報告的SO鏈接都已經死機,我一直無法找到任何其他鏈接。

+1

上一個問題在2009年回覆,它仍然適用? –

+0

好問題。我只是把馬丁的代碼放在VS裏(稍作調整)。如果我的目標是.NET 4,代碼將按預期工作。如果我以3.5爲目標,我會看到馬丁描述的奇怪行爲。 –

+0

它不適用。兩個問題都是相似的,但另一個問題有一個額外的異常變量'tex',並且(正確的)答案是刪除該變量。在我的情況下,我沒有使用變量,所以答案不適用於這種情況。 –

0

(這不是一個具體的答案。但我不能將它張貼作爲評論太)

我不能重現這個(VS 2012,.NET 4.5,C#5.0,安裝在每臺SP)。

我所限定的本異常類:

class MyException : Exception 
{ 
    public MyException() { } 
    public MyException(string message) : base(message) { } 
} 

和方法:

static void Throws<T>(Action action) where T : Exception 
{ 
    try 
    { 
     action(); 
    } 
    catch (T) { Console.WriteLine("got {0}", typeof(T)); } 
    catch (Exception) { Console.WriteLine("got Exception"); } 
} 

和我已經測試這種方式:

Throws<MyException>(() => { throw new MyException(); }); 

int result = 0; 
Throws<DivideByZeroException>(() => result = result/result); 

並且輸出是:

  • 得到Draft.MyException
  • 得到系統。DivideByZeroException

所以(恕我直言)你應該找別的地方。