如何使用Assert(或其餘Test類?)來驗證是否拋出了異常? html
好吧,我幾乎能夠總結一下以前全部其餘人所說的內容......不管如何,這裏是我根據好的答案創建的代碼:)剩下要作的就是複製和使用...... 框架
/// <summary> /// Checks to make sure that the input delegate throws a exception of type TException. /// </summary> /// <typeparam name="TException">The type of exception expected.</typeparam> /// <param name="methodToExecute">The method to execute to generate the exception.</param> public static void AssertRaises<TException>(Action methodToExecute) where TException : System.Exception { try { methodToExecute(); } catch (TException) { return; } catch (System.Exception ex) { Assert.Fail("Expected exception of type " + typeof(TException) + " but type of " + ex.GetType() + " was thrown instead."); } Assert.Fail("Expected exception of type " + typeof(TException) + " but no exception was thrown."); }
@Richiban上面提供的幫助程序工做得很好,除了它不處理拋出異常的狀況,但不處理預期的類型。 如下內容涉及: 測試
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace YourProject.Tests { public static class MyAssert { /// <summary> /// Helper for Asserting that a function throws an exception of a particular type. /// </summary> public static void Throws<T>( Action func ) where T : Exception { Exception exceptionOther = null; var exceptionThrown = false; try { func.Invoke(); } catch ( T ) { exceptionThrown = true; } catch (Exception e) { exceptionOther = e; } if ( !exceptionThrown ) { if (exceptionOther != null) { throw new AssertFailedException( String.Format("An exception of type {0} was expected, but not thrown. Instead, an exception of type {1} was thrown.", typeof(T), exceptionOther.GetType()), exceptionOther ); } throw new AssertFailedException( String.Format("An exception of type {0} was expected, but no exception was thrown.", typeof(T)) ); } } } }
若是你使用NUNIT,你能夠這樣作: spa
Assert.Throws<ExpectedException>(() => methodToTest());
還能夠存儲拋出的異常以進一步驗證它: 設計
ExpectedException ex = Assert.Throws<ExpectedException>(() => methodToTest()); Assert.AreEqual( "Expected message text.", ex.Message ); Assert.AreEqual( 5, ex.SomeNumber);
請參閱: http : //nunit.org/docs/2.5/exceptionAsserts.html code
我不建議使用ExpectedException屬性(由於它過於約束和容易出錯)或者在每一個測試中編寫一個try / catch塊(由於它太複雜且容易出錯)。 使用設計良好的斷言方法 - 由測試框架提供或編寫本身的方法。 這是我寫的和使用的。 orm
public static class ExceptionAssert { private static T GetException<T>(Action action, string message="") where T : Exception { try { action(); } catch (T exception) { return exception; } throw new AssertFailedException("Expected exception " + typeof(T).FullName + ", but none was propagated. " + message); } public static void Propagates<T>(Action action) where T : Exception { Propagates<T>(action, ""); } public static void Propagates<T>(Action action, string message) where T : Exception { GetException<T>(action, message); } public static void Propagates<T>(Action action, Action<T> validation) where T : Exception { Propagates(action, validation, ""); } public static void Propagates<T>(Action action, Action<T> validation, string message) where T : Exception { validation(GetException<T>(action, message)); } }
示例用途: htm
[TestMethod] public void Run_PropagatesWin32Exception_ForInvalidExeFile() { (test setup that might propagate Win32Exception) ExceptionAssert.Propagates<Win32Exception>( () => CommandExecutionUtil.Run(Assembly.GetExecutingAssembly().Location, new string[0])); (more asserts or something) } [TestMethod] public void Run_PropagatesFileNotFoundException_ForExecutableNotFound() { (test setup that might propagate FileNotFoundException) ExceptionAssert.Propagates<FileNotFoundException>( () => CommandExecutionUtil.Run("NotThere.exe", new string[0]), e => StringAssert.Contains(e.Message, "NotThere.exe")); (more asserts or something) }
筆記 blog
返回異常而不是支持驗證回調是一個合理的想法,除了這樣作使得這個斷言的調用語法與我使用的其餘斷言很是不一樣。 繼承
與其餘人不一樣,我使用'propagates'而不是'throws',由於咱們只能測試異常是否從調用傳播。 咱們沒法直接測試拋出異常。 可是我想你能夠將投射圖像意味着:拋出而不是被抓住。
最後的想法
在切換到這種方法以前,我考慮使用ExpectedException屬性,當測試僅驗證異常類型並使用try / catch塊時,若是須要更多驗證。 可是,我不只要考慮每種測試使用哪一種技術,並且在須要改變時將代碼從一種技術改成另外一種技術並非一件容易的事。 使用一致的方法能夠節省精力。
總而言之,這種方法運動:易用性,靈活性和穩健性(很難作錯)。
您可使用如下命令從Nuget下載程序包: PM> Install-Package MSTestExtensions ,它將nUnit / xUnit樣式的Assert.Throws()語法添加到MsTest。
高級指令:下載程序集並從BaseTest繼承,您可使用Assert.Throws()語法。
Throws實現的主要方法以下:
public static void Throws<T>(Action task, string expectedMessage, ExceptionMessageCompareOptions options) where T : Exception { try { task(); } catch (Exception ex) { AssertExceptionType<T>(ex); AssertExceptionMessage(ex, expectedMessage, options); return; } if (typeof(T).Equals(new Exception().GetType())) { Assert.Fail("Expected exception but no exception was thrown."); } else { Assert.Fail(string.Format("Expected exception of type {0} but no exception was thrown.", typeof(T))); } }
披露:我把這個包放在一塊兒。
更多信息: http : //www.bradoncode.com/blog/2012/01/asserting-exceptions-in-mstest-with.html