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


当前回答

好吧,我来总结一下大家之前说过的话…不管怎样,这是我根据好的答案构建的代码:)剩下要做的就是复制和使用…

/// <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.");  
}

其他回答

这取决于您使用的测试框架?

例如,在MbUnit中,您可以用一个属性指定预期的异常,以确保您得到的是真正预期的异常。

[ExpectedException(typeof(ArgumentException))]

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

//Arrange

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

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

通常你的测试框架会给出答案。但如果它不够灵活,你可以这样做:

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();
}

你可以从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

FluentAssertions例子

为那些使用该库的用户添加一个使用FluentAssertions的示例。

// act
Action result = () => {
    sut.DoSomething();
};

// assert
result.Should().Throw<Exception>();

异步的例子

// act
Func<Task> result = async () => {
    await sut.DoSomethingAsync();
};

// assert
await result.Should().ThrowAsync<Exception>();