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


当前回答

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

其他回答

我知道这个帖子很老了,有很多很好的答案,但值得一提的是,局部函数可以以一种非常简单的方式提供帮助。

//Arrange

//Act
void LocalFunction() => mr.ActualMethod(params);

//Assert
Assert.Throws<Exception>(LocalFunction);

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

使用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/

这适用于Visual Studio Team Test(又名MSTest) 在处理数据库或http事务时。系统应该在某处抛出异常,使用Assert.ThrowExceptionAsync<>()将捕获您的throw事件。(在这些情况下,Assert.ThrowException<>()不会捕获异常)。

   [TestMethod]
   public void Invalid_Input_UserName_Should_Throw_Exception()
   {
       await Assert.ThrowExceptionAsync<ExpectedExceptionType>(()=> new LogonInfo(InvalidInputInUserNameFormat,"P@ssword"));
   }

有一个很棒的库叫做NFluent,它可以加速和简化你编写断言的方式。

编写抛出异常的断言非常简单:

    [Test]
    public void given_when_then()
    {
        Check.ThatCode(() => MethodToTest())
            .Throws<Exception>()
            .WithMessage("Process has been failed");
    }