如何使用Assert.Throws来断言异常的类型?

epi*_*tka 226 c# nunit exception assertions

如何使用Assert.Throws断言异常的类型和实际的消息措辞.

像这样的东西:

Assert.Throws<Exception>(
    ()=>user.MakeUserActive()).WithMessage("Actual exception message")
Run Code Online (Sandbox Code Playgroud)

我正在测试的方法抛出多个相同类型的消息,使用不同的消息,我需要一种方法来测试是否根据上下文抛出了正确的消息.

Pat*_*gne 408

Assert.Throws 返回抛出的异常,它允许您对异常进行断言.

var ex = Assert.Throws<Exception>(() => user.MakeUserActive());
Assert.That(ex.Message, Is.EqualTo("Actual exception message"));
Run Code Online (Sandbox Code Playgroud)

因此,如果没有抛出异常,或抛出错误类型的异常,则第一个Assert.Throws断言将失败.但是,如果抛出了正确类型的异常,那么现在可以断言已保存在变量中的实际异常.

通过使用此模式,您可以在除异常消息之外的其他事物上断言,例如在ArgumentException和衍生物的情况下,您可以声明参数名称是正确的:

var ex = Assert.Throws<ArgumentNullException>(() => foo.Bar(null));
Assert.That(ex.ParamName, Is.EqualTo("bar"));
Run Code Online (Sandbox Code Playgroud)

您还可以使用流畅的API来执行这些断言:

Assert.That(() => foo.Bar(null), 
Throws.Exception
  .TypeOf<ArgumentNullException>()
  .With.Property("ParamName")
  .EqualTo("bar"));
Run Code Online (Sandbox Code Playgroud)

在异常消息上断言时的一个小提示是使用它来装饰测试方法,SetCultureAttribute以确保抛出的消息正在使用预期的文化.如果您将异常消息存储为允许本地化的资源,则会发挥作用.

  • +1感谢您显示Fluent API,由于某些原因,我仅仅从NUnit文档中了解如何使用它时遇到了问题. (5认同)

Jac*_*ope 24

您现在可以使用ExpectedException属性,例如

[Test]
[ExpectedException(typeof(InvalidOperationException), 
 ExpectedMessage="You can't do that!"]
public void MethodA_WithNull_ThrowsInvalidOperationException()
{
    MethodA(null);
}
Run Code Online (Sandbox Code Playgroud)

  • NUnit 3中不推荐使用ExpectedException属性:https://github.com/nunit/docs/wiki/Breaking-Changes (20认同)
  • +1也是测试异常的好方法.关于这一点唯一要记住的是理论上,任何抛出InvalidOperationException和该消息的代码行都将通过测试,包括测试中的代码,它准备测试数据/对象或者在执行之前可能需要执行的任何其他方法.你有兴趣测试,可能导致误报.当然,这取决于消息的具体程度以及您正在测试的异常类型.使用`Assert.Throw`,您可以定位您感兴趣的确切行. (14认同)
  • 初次见面时,这让我有些不安,因为测试表象没有断言,这对我来说是一种气味。这是一个很好的功能,但是应该在团队中讨论该属性应在Assert上使用的情况。 (2认同)

Jor*_*ris 13

Assert.That(myTestDelegate, Throws.ArgumentException
    .With.Property("Message").EqualTo("your argument is invalid."));
Run Code Online (Sandbox Code Playgroud)

  • 随着nameof运算符的引入,我将编辑这个优秀的anwser:`Assert.That(myTestDelegate,Throws.ArgumentException .With.Property(nameof(ArgumentException.Message)).EqualTo("你的参数无效.")); ` (2认同)

Dus*_*_00 6

对于那些使用NUnit 3.0 约束模型并最终到达这里的人:

Assert.That(() => MethodUnderTest(someValue), Throws.TypeOf<ArgumentException>());
Run Code Online (Sandbox Code Playgroud)


Tvd*_*de1 5

一个实际有效的解决方案:

public void Test() {
    throw new MyCustomException("You can't do that!");
}

[TestMethod]
public void ThisWillPassIfExceptionThrown()
{
    var exception = Assert.ThrowsException<MyCustomException>(
        () => Test(),
        "This should have thrown!");
    Assert.AreEqual("You can't do that!", exception.Message);
}
Run Code Online (Sandbox Code Playgroud)

这适用于using Microsoft.VisualStudio.TestTools.UnitTesting;.