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


当前回答

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

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

其他回答

您可以通过简单的一行代码来实现这一点。

如果你的foo.bar()操作是异步的:

await Assert.ThrowsExceptionAsync<Exception>(() => foo.bar());

如果foo.bar()不是异步的

Assert.ThrowsException<Exception>(() => foo.bar());

对于“Visual Studio Team Test”,似乎您将ExpectedException属性应用到测试的方法。

文档中的示例:使用Visual Studio团队测试的单元测试演练

[TestMethod]
[ExpectedException(typeof(ArgumentException),
    "A userId of null was inappropriately allowed.")]
public void NullUserIdInConstructor()
{
   LogonInfo logonInfo = new LogonInfo(null, "P@ss0word");
}

在我正在做的一个项目中,我们有另一个解决方案。

首先,我不喜欢ExpectedExceptionAttribute,因为它确实考虑了导致异常的方法调用。

我用一个helper方法来代替它。

Test

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

HelperMethod

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

很整洁,不是吗?)

作为一种替代方法,您可以尝试测试异常实际上是在您的测试中的下两行中抛出的。

var testDelegate = () => MyService.Method(params);
Assert.Throws<Exception>(testDelegate);

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

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

[ExpectedException(typeof(ArgumentException))]