使用 NUnit Assert.Throws 方法或 ExpectedException 属性?

Posted

技术标签:

【中文标题】使用 NUnit Assert.Throws 方法或 ExpectedException 属性?【英文标题】:Use NUnit Assert.Throws method or ExpectedException attribute? 【发布时间】:2013-02-07 11:55:59 【问题描述】:

我发现这些似乎是测试异常的两种主要方法:

Assert.Throws<Exception>(()=>MethodThatThrows());

[ExpectedException(typeof(Exception))]

其中哪一个最好?一个比另一个有优势吗?还是仅仅是个人喜好问题?

【问题讨论】:

第三个选项是流畅的风格:Assert.That(() =&gt; MethodThatThrows(), Throws.Exception) NUnit 版本 3 及更高版本不再支持 ExpectedException 属性,因此对于版本 3+,只有 Assert.Throws 变体是相关的。 为什么会这样?那 Nunit3 决定放弃那个支持?正在谷歌搜索,找不到解释...... JUnit 仍然支持这种方式,不是吗? 【参考方案1】:

我更喜欢 assert.throws,因为它允许我在抛出异常后验证和断言其他条件。

    [Test]
    [Category("Slow")]
    public void IsValidLogFileName_nullFileName_ThrowsExcpetion()
    
        var a = new MyTestObject();

        // the exception we expect thrown from the IsValidFileName method
        var ex = Assert.Throws<ArgumentNullException>(() => a.IsValidLogFileName(""));

        // now we can test the exception itself
        Assert.That(ex.Message == "Blah");

    

【讨论】:

这是更好的答案之一,您想在抛出异常后验证某些东西是否进入错误状态是很常见的。 好答案!但是[Category("Slow")]a是什么意思呢? 您可以使用类别来对您的测试进行分组 - 本示例不需要它 - 在这种情况下,“慢”可能意味着希望能够选择是否每次都运行“慢”测试或仅作为每晚或每周跑步或其他东西的一部分。我相信“a”在技术上是一个语法错误,但它只是您正在测试的对象。【参考方案2】:

如果您使用的是NUnit 的旧版本(),那么您需要使用ExpectedException

如果您使用的是 2.5 或更高版本,则可以使用Assert.Throw()

https://github.com/nunit/docs/wiki/Breaking-Changes

使用方法: https://www.nunit.org/index.php?p=exceptionAsserts&r=2.5

【讨论】:

【参考方案3】:

您也可以强输入您期望的错误(如旧的属性版本)。

Assert.Throws<System.InvalidOperationException>(() => breakingAction())

【讨论】:

【参考方案4】:

主要区别在于:

ExpectedException() 属性在测试方法中任何处发生异常时使测试通过。Assert.Throws() 的使用允许指定 exact 代码的位置,其中预期异常。

NUnit 3.0 完全放弃了对 ExpectedException 的官方支持。

所以,我绝对更喜欢使用Assert.Throws() 方法而不是ExpectedException() 属性。

【讨论】:

这是迄今为止正确的答案。顺便说一句,Assert.Throws() 也返回异常,如果它们对您很重要,它可以允许对异常的属性进行额外检查。 最后回答为什么我不能让 ExpectedException 工作.. 使用版本 3。 这里是链接 github.com/nunit/docs/wiki/Breaking-Changes - ExpectedExceptionAttribute 不再支持。 要将其更改为在 NUnit 3.0 下工作,请将其更改为 the following【参考方案5】:

第一个允许您通过多次调用测试多个异常:

Assert.Throws(()=>MethodThatThrows());
Assert.Throws(()=>Method2ThatThrows());

第二个只允许您为每个测试函数测试一个异常。

【讨论】:

一个测试应该只测试一个不同的逻辑位,那么在同一个单元测试中测试两个错误不会被认为是不好的做法吗? @SamuelDavis - 通常你不想在同一个测试中测试不同的案例。但是,多个Assert.Throws 可能会有一些用例。 无论哪种方式,在这里您都可以将异常作为参数获取,这允许您在异常中断言详细信息。此外,使用“预期异常”并不能保护您在另一个方法调用中抛出相同的异常类型。在这里,您针对的是确切的方法,而不是整个测试。即使你的测试应该调用很少的代码,你也永远不会太安全。特别是当代码变得复杂和/或异常过于通用时。诸如“ArgumentNullExceptions”之类的东西可能会被抛出很多,例如使用 ExpectedException 很容易错过。 Assert.Throws 不会错过。

以上是关于使用 NUnit Assert.Throws 方法或 ExpectedException 属性?的主要内容,如果未能解决你的问题,请参考以下文章

你如何用 NUnit 测试私有方法?

使用NMock的虚拟工厂方法帮助NUnit测试

并非我的所有 NUnit 测试方法都在测试资源管理器中可见

单元测试之NUnit二

如何在测试拆解时使用 NUnit 3 读取 ITestResult

使用 Fluentassertions 和 Nunit 在单元测试中进行计数验证