如何使用Assert(或其他Test类?)来验证是否抛出了异常?
#1楼
好吧,我几乎可以总结一下之前所有其他人所说的内容......无论如何,这里是我根据好的答案建立的代码:)剩下要做的就是复制和使用......
///
/// Checks to make sure that the input delegate throws a exception of type TException.
///
/// The type of exception expected.
/// The method to execute to generate the exception.
public static void AssertRaises(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.");
}
#2楼
@Richiban上面提供的帮助程序工作得很好,除了它不处理抛出异常的情况,但不处理预期的类型。 以下内容涉及:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace YourProject.Tests
{
public static class MyAssert
{
///
/// Helper for Asserting that a function throws an exception of a particular type.
///
public static void Throws( 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))
);
}
}
}
}
#3楼
如果你使用NUNIT,你可以这样做:
Assert.Throws(() => methodToTest());
还可以存储抛出的异常以进一步验证它:
ExpectedException ex = Assert.Throws(() => methodToTest());
Assert.AreEqual( "Expected message text.", ex.Message );
Assert.AreEqual( 5, ex.SomeNumber);
#4楼
我不建议使用ExpectedException属性(因为它过于约束和容易出错)或者在每个测试中编写一个try / catch块(因为它太复杂且容易出错)。 使用设计良好的断言方法 - 由测试框架提供或编写自己的方法。 这是我写的和使用的。
public static class ExceptionAssert
{
private static T GetException(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(Action action) where T : Exception
{
Propagates(action, "");
}
public static void Propagates(Action action, string message) where T : Exception
{
GetException(action, message);
}
public static void Propagates(Action action, Action validation) where T : Exception
{
Propagates(action, validation, "");
}
public static void Propagates(Action action, Action validation, string message) where T : Exception
{
validation(GetException(action, message));
}
}
示例用途:
[TestMethod]
public void Run_PropagatesWin32Exception_ForInvalidExeFile()
{
(test setup that might propagate Win32Exception)
ExceptionAssert.Propagates(
() => 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(
() => CommandExecutionUtil.Run("NotThere.exe", new string[0]),
e => StringAssert.Contains(e.Message, "NotThere.exe"));
(more asserts or something)
}
笔记
返回异常而不是支持验证回调是一个合理的想法,除了这样做使得这个断言的调用语法与我使用的其他断言非常不同。
与其他人不同,我使用'propagates'而不是'throws',因为我们只能测试异常是否从调用传播。 我们无法直接测试抛出异常。 但是我想你可以将投射图像意味着:抛出而不是被抓住。
最后的想法
在切换到这种方法之前,我考虑使用ExpectedException属性,当测试仅验证异常类型并使用try / catch块时,如果需要更多验证。 但是,我不仅要考虑每种测试使用哪种技术,而且在需要改变时将代码从一种技术改为另一种技术并不是一件容易的事。 使用一致的方法可以节省精力。
总而言之,这种方法运动:易用性,灵活性和稳健性(很难做错)。
#5楼
您可以使用以下命令从Nuget下载程序包: PM> Install-Package MSTestExtensions ,它将nUnit / xUnit样式的Assert.Throws()语法添加到MsTest。
高级指令:下载程序集并从BaseTest继承,您可以使用Assert.Throws()语法。
Throws实现的主要方法如下:
public static void Throws(Action task, string expectedMessage, ExceptionMessageCompareOptions options) where T : Exception
{
try
{
task();
}
catch (Exception ex)
{
AssertExceptionType(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)));
}
}
披露:我把这个包放在一起。