我如何使用Assert(或其他测试类)来验证在使用MSTest/Microsoft.VisualStudio.TestTools.UnitTesting时抛出了异常?


当前回答

查看nUnit文档中的例子:

[ExpectedException( typeof( ArgumentException ) )]

其他回答

我最喜欢的实现方法是编写一个名为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());
}

它的外观和行为更像单元测试语法的其余部分。

使用ExpectedException时要谨慎,因为它可能导致如下所示的几个陷阱:

Link

在这里:

http://xunit.github.io/docs/comparisons.html

如果需要测试异常,有一些不太受欢迎的方法。您可以使用try{act/fail}catch{assert}方法,该方法对于除了ExpectedException之外不直接支持异常测试的框架非常有用。

更好的选择是使用xUnit。NET,这是一个非常现代的、前瞻性的、可扩展的单元测试框架,它已经从所有其他错误中吸取了教训,并进行了改进。Assert就是这样一种改进。它为断言异常提供了更好的语法。

你可以找到xUnit。NET在github: http://xunit.github.io/

上面@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))
                    );
            }
        }
    }
}

在VS内置单元测试中,如果你只是想验证抛出了“任何异常”,但你不知道类型,你可以使用catch all:

[TestMethod]
[ExpectedException(typeof(Exception), AllowDerivedTypes = true)]
public void ThrowExceptionTest()
{
    //...
}

你可以从Nuget下载一个包,使用:PM> Install-Package MSTestExtensions将Assert.Throws()语法以nUnit/xUnit的风格添加到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