2013-12-10 38 views
6

我需要編寫用於下一功能的單元測試和我看到我可以使用[的ExpectedException]的ExpectedException斷言

這是要測試的功能。

public static T FailIfEnumIsNotDefined<T>(this T enumValue, string message = null) 
     where T:struct 
    { 
     var enumType = typeof (T); 

     if (!enumType.IsEnum) 
     { 
      throw new ArgumentOutOfRangeException(string.Format("Type {0} is not an Enum, therefore it cannot be checked if it is Defined not have defined.", enumType.FullName)); 
     } 
     else if (!Enum.IsDefined(enumType, enumValue)) 
     { 
      throw new ArgumentOutOfRangeException(string.Format("{1} Value {0} is not does not have defined value in Enum of type {0}. It should not be...", enumType.FullName, message ?? "")); 
     } 

     return enumValue; 
    } 

這裏會去的代碼來測試應該在異常被拋出

[TestMethod] 
    [ExpectedException(ArgumentOutOfRangeException(ArgumentException), "message")] 
    public void FailIfEnumIsNotDefined_Check_That_The_Value_Is_Not_Enum() 
    { 
     // PREPARE 
     // EXECUTE 
     // ASSERT 
    } 

我沒有想法不得不作出的例外斷言無論是。

+1

使用'Assert.Throws()'而不是'ExpectedException',因爲該屬性使得測試通過,如果exc eption發生在測試方法代碼的任何部分。 'Assert.Throws'允許在出現異常的地方測試代碼的確切位置。 – sthotakura

+0

@sthotakura MSTest不具有Assert.Throws,除非您編寫自定義的一個,無論如何,這是首選的MSTest異常處理。類似於NUnit :)我的回答中有一個鏈接 – Spock

+0

@Spock我不知道,謝謝! – sthotakura

回答

17

ExpectedException只是斷言指定類型的該異常將通過試驗方法拋出:

[TestMethod] 
[ExpectedException(typeof(ArgumentOutOfRangeException))] 
public void FailIfEnumIsNotDefined_Check_That_The_Value_Is_Not_Enum() 
{ 
    // PREPARE 
    // EXECUTE 
    // NO ASSERT!! 
} 

如果要斷言異常的其他參數,那麼你應該在你的測試方法使用try..catch

[TestMethod]  
public void FailIfEnumIsNotDefined_Check_That_The_Value_Is_Not_Enum() 
{ 
    // PREPARE 

    try 
    { 
     // EXECUTE 
     Assert.Fail() 
    } 
    catch(Exception exception) 
    {   
     // ASSERT EXCEPTION DETAILS 
    } 
} 

你可以編寫自己的斷言異常的方法來避免重複相同的測試代碼:

public TException AssertCatch<TException>(Action action) 
    where TException : Exception 
{ 
    try 
    { 
     action(); 
    } 
    catch (TException exception) 
    { 
     return exception; 
    } 

    throw new AssertFailedException("Expected exception of type " + 
            typeof(TException) + " was not thrown"); 
} 

用法:

var exception = AssertCatch<ArgumentOutOfRangeException>(() => /* EXECUTE */); 
Assert.AreEqual("foo", exception.Message); 
2

您必須使用不同ExpectedException

[TestMethod] 
[ExpectedException(typeof(ArgumentOutOfRangeException))] 
public void MyTestSomething() 

,然後使預期的異常被拋出編寫測試。

1

您可能想要查找更多自定義異常處理。 MSTest ExpectedException attr有幾個缺陷。嘗試使用this方法,它可以很好地控制拋出的異常。

1

斷言例外的是用正確的異常消息拋出:

var ex = Assert.Throws<Exception>(() => _foo.DoSomething(a, b, c)); 
Assert.That(ex.Message, Is.EqualTo("Your exception message")); 
1

雖然ExpectedException不能直接使用,主要是驗證異常的信息,您可以通過從ExpectedExceptionBaseAttribute繼承實現自己的異常驗證邏輯:

通過實施您自己的預期異常驗證。你可以 指定內置 方法ExpectedExceptionAttribute類不能處理的,如 以下附加信息及要求:

  • 驗證異常的狀態。
  • 預計會有多種類型的異常。
  • 當拋出錯誤類型的異常時顯示自定義消息。
  • 控制陰性測試的結果。

在你的情況下,它可能是這個樣子:

public sealed class ExpectedExceptionMessageAttribute<T> : ExpectedExceptionBaseAttribute 
{ 
    readonly string _expectedMessage; 
    public ExpectedExceptionMessageAttribute(string expectedMessage) 
    { 
     _expectedMessage = expectedMessage; 
    } 

    protected override void Verify(System.Exception exception) 
    { 
     // Handle assertion exceptions from assertion failures in the test method 
     base.RethrowIfAssertException(exception); 

     Assert.IsInstanceOfType(exception, typeof(T), "wrong exception type"); 
     Assert.AreEqual(_expectedMessage, exception.Message, "wrong exception message"); 
    } 
} 

話雖如此,我仍然傾向於使用直接try - catch的做法,雖然,因爲它是在更具體預期將拋出異常:

public static void Throws<T>(Action action, Predicate<T> predicate = null) 
        where T : Exception 
{ 
    try 
    { 
     action(); 
    } 
    catch (T e) 
    { 
     if (predicate == null || predicate(e)) 
     { 
      return; 
     } 

     Assert.Fail($"Exception of type {typeof(T)} thrown as expected, but the provided predicate rejected it: {e}"); 
    } 
    catch (Exception e) 
    { 
     Assert.Fail($"Expected exception of type {typeof(T)} but a different exception was thrown: {e}"); 
    } 

    Assert.Fail($"No exception thrown, expected {typeof(T)}"); 
}