对于 “Visual Studio Team Test”,您似乎将 ExpectedException 属性应用于该测试的方法。
这里的文档样本: 使用 Visual Studio Team Test 进行单元测试的演练
[TestMethod]
[ExpectedException(typeof(ArgumentException),
"A userId of null was inappropriately allowed.")]
public void NullUserIdInConstructor()
{
LogonInfo logonInfo = new LogonInfo(null, "P@ss0word");
}
通常,您的测试框架会对此提供答案。但是,如果它不够灵活,可以随时执行以下操作:
try {
somethingThatShouldThrowAnException();
Assert.Fail(); // If it gets to this line, no exception was thrown
} catch (GoodException) { }
正如 @Jonas 指出的那样,这对于捕获基本异常无效:
try {
somethingThatShouldThrowAnException();
Assert.Fail(); // raises AssertionException
} catch (Exception) {
// Catches the assertion exception, and the test passes
}
如果绝对必须捕获 Exception,则需要重新抛出 Assert.Fail()。但是,实际上,这是一个不应该手写的迹象;检查测试框架中的选项,或者查看是否可以抛出更有意义的异常以进行测试。
catch (AssertionException) { throw; }
您应该能够使此方法适应您喜欢的任何方式 - 包括指定要捕获的异常类型。如果只希望使用某些类型,请使用以下方法结束catch
:
} catch (GoodException) {
} catch (Exception) {
// not the right kind of exception
Assert.Fail();
}
实现此目的的首选方法是编写一个称为 Throws 的方法,并像其他任何 Assert 方法一样使用它。不幸的是,.NET 不允许您编写静态扩展方法,因此您无法像使用该方法实际上属于 Assert 类中的内部版本一样使用此方法。只需创建另一个名为 MyAssert 或类似名称的文件即可。该类如下所示:
using System;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace YourProject.Tests
{
public static class MyAssert
{
public static void Throws<T>( Action func ) where T : Exception
{
var exceptionThrown = false;
try
{
func.Invoke();
}
catch ( T )
{
exceptionThrown = true;
}
if ( !exceptionThrown )
{
throw new AssertFailedException(
String.Format("An exception of type {0} was expected, but not thrown", typeof(T))
);
}
}
}
}
这意味着您的单元测试如下所示:
[TestMethod()]
public void ExceptionTest()
{
String testStr = null;
MyAssert.Throws<NullReferenceException>(() => testStr.ToUpper());
}
它的外观和行为更像其余的单元测试语法。
如果您使用的是 MSTest(最初没有ExpectedException
属性),则可以执行以下操作:
try
{
SomeExceptionThrowingMethod()
Assert.Fail("no exception thrown");
}
catch (Exception ex)
{
Assert.IsTrue(ex is SpecificExceptionType);
}
如果您使用 NUNIT,则可以执行以下操作:
Assert.Throws<ExpectedException>(() => methodToTest());
还可以存储抛出的异常以便进一步验证它:
ExpectedException ex = Assert.Throws<ExpectedException>(() => methodToTest());
Assert.AreEqual( "Expected message text.", ex.Message );
Assert.AreEqual( 5, ex.SomeNumber);
谨慎使用 ExpectedException,因为它可能导致以下陷阱:
http://geekswithblogs.net/sdorman/archive/2009/01/17/unit-testing-and-expected-exceptions.aspx
和这里:
http://xunit.github.io/docs/comparisons.html
如果您需要测试例外情况,那么对方法的皱眉就更少了。您可以使用 try {act / fail} catch {assert} 方法,该方法对于不直接支持除 ExpectedException 之外的异常测试的框架很有用。
更好的替代方法是使用 xUnit.NET,它是一个非常现代,具有前瞻性和可扩展性的单元测试框架,该框架从其他所有错误中吸取了教训并进行了改进。 Assert.Throws 是这样的改进之一,它为断言提供了更好的语法。
您可以在 github 上找到 xUnit.NET: http://xunit.github.io/
在一个正在进行的项目中,我们有另一个解决方案。
首先,我不喜欢 ExpectedExceptionAttribute,因为它确实考虑了导致异常的方法调用。
我用一种辅助方法来代替。
测试
[TestMethod]
public void AccountRepository_ThrowsExceptionIfFileisCorrupt()
{
var file = File.Create("Accounts.bin");
file.WriteByte(1);
file.Close();
IAccountRepository repo = new FileAccountRepository();
TestHelpers.AssertThrows<SerializationException>(()=>repo.GetAll());
}
辅助方法
public static TException AssertThrows<TException>(Action action) where TException : Exception
{
try
{
action();
}
catch (TException ex)
{
return ex;
}
Assert.Fail("Expected exception was not thrown");
return null;
}
整洁,不是吗?)
MSTest(v2)现在具有一个 Assert.ThrowsException 函数,可以像这样使用:
Assert.ThrowsException<System.FormatException>(() =>
{
Story actual = PersonalSite.Services.Content.ExtractHeader(String.Empty);
});
您可以使用 nuget 进行Install-Package MSTest.TestFramework
: Install-Package MSTest.TestFramework
它是测试方法的一个属性... 您不使用 Assert。看起来像这样:
[ExpectedException(typeof(ExceptionType))]
public void YourMethod_should_throw_exception()
您可以使用以下方法从 Nuget 下载软件包: PM> Install-Package MSTestExtensions ,它以 nUnit / xUnit 样式向 MsTest 添加了Assert.Throws()语法。
高级说明:下载程序集并从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