C# 我怎么能期待 Assert.AreEqual 中的异常?

Posted

技术标签:

【中文标题】C# 我怎么能期待 Assert.AreEqual 中的异常?【英文标题】:C# How I can expect a exception in Assert.AreEqual? 【发布时间】:2015-07-31 09:22:56 【问题描述】:

示例:

Assert.AreEqual(**null**, Program.nDaysMonth(5, -10), "Error nDaysMonth, Month may -10.");

我期待一个例外。我怎么能期待 Assert.AreEqual 中的异常?

谢谢。

【问题讨论】:

如果您期望异常,为什么要使用Assert?为什么不用ExpectedException 来装饰你的方法呢? 请参阅:***.com/questions/933613/… - 如果这不能满足您的需求,请添加额外信息说明为什么不这样做。 您是在问如何编写单元测试来验证Program.nDaysMonth(5, -10) 是否抛出异常? @YuvalItzchakov 你不应该使用 ExpectedException 属性,它不好。而不是这个使用 Assert.Throws 方法。然后你就知道异常发生在哪里,测试写得更好。 请指定您正在使用的单元测试框架 - 我们无法仅从您的代码 sn-p 中看出这一点。 【参考方案1】:

如果您使用的是 Microsoft 测试框架,则需要使用 ExpectedExceptionAttribute 装饰方法:

[TestClass]
public class UnitTest1

    [TestMethod]
    [ExpectedException(typeof(ArgumentOutOfRangeException))]
    public void TestMethod1()
    
        //Do whatever causes the exception here
    

然后测试将通过或失败取决于是否抛出异常。

但是,正如 Jon 在下面指出的那样,请找到一个支持 Assert.Throws 或其中一些变体的测试框架。使用预期的异常进行装饰可能会导致代码中的错误传递或其他问题,具体取决于您正在执行的操作,并且在方法中引发异常后很难执行任何操作。使用功能齐全的框架将显着提高测试质量。

我推荐 NUnit,http://www.nunit.org/

或者还有XUnit之类的https://github.com/xunit/xunit

或其他几十个:http://en.wikipedia.org/wiki/List_of_unit_testing_frameworks#.NET_programming_languages

【讨论】:

这是一个坏主意(IMO),原因在我的回答中的评论中列出。将预期异常的范围限制为 lambda 表达式是更干净的 IMO。 我同意,但是不要自己动手,只使用 MS 可用的东西(用于快速测试),这是唯一的选择。在我看来,如果它是在该方法中进行的唯一测试,那么它很重要。 那么你几乎需要用属性来装饰方法,不是吗?那只是如果您不想费心重新实现Assert.Throws - 这非常简单,并且使您的所有其余测试更加清晰,IMO。我肯定会建议这样做(或切换到过去没有卡住的测试框架......) 谢谢。我用 [ExpectedException] 做到了。【参考方案2】:

你不用Assert.AreEqual,你用Assert.Throws

Assert.Throws<ArgumentOutOfRangeException>(() => Program.nDaysMonth(5, -10));

这会检查是否抛出了正确的异常。如果要添加更多的断言,可以使用返回值:

var exception = Assert.Throws<ArgumentOutOfRangeException>(...);
Assert.AreEqual("Foo", exception.Message); // Or whatever

这至少适用于 NUnit 和 xUnit;如果您使用不同的测试框架,您应该寻找类似的功能。如果它不存在,我建议您自己实现它——它很容易做到,而且比替代品(try/catch 块,或方法范围的ExpectedException 属性)更干净。或者,如果可以的话,更改单元测试框架...

我还强烈建议您开始遵循正常的 .NET 命名约定 - nDaysMonth 不是一个好的方法名称...

一些框架支持使用 [ExpectedException] 属性来装饰方法 - 我建议 反对 使用它:

    这使得测试不清楚您希望在哪里引发异常。 如果在测试方法的其他地方抛出异常(即您的代码已损坏),测试仍将通过。 抛出异常后,您无法执行任何其他操作。 您无法检查有关异常的任何其他内容。

【讨论】:

Assert 没有名为 Throws 的方法。还是我错过了什么? @oleksii: 1) 这使得测试不清楚您希望在哪里抛出异常。 2)如果在测试方法的其他地方抛出异常(即您的代码被破坏),测试仍然会通过。 3) 抛出异常后,你不能做任何其他事情。 4)您无法检查有关异常的任何其他内容。基本上,这是个坏主意。 @YuvalItzchakov:没有一个单独的 Assert 类用于单元测试 - NUnit 中的一个,xUnit 中的一个,Microsoft Test 中的一个,等等。 @YuvalItzchakov:我在回答中已经明确说明了这一点。 @Jesús:你读过我为什么使用ExpectedException 是个坏主意吗?

以上是关于C# 我怎么能期待 Assert.AreEqual 中的异常?的主要内容,如果未能解决你的问题,请参考以下文章

为啥 Assert.AreEqual(1.0, double.NaN, 1.0) 通过?

NUnit Assert.AreEqual DateTime 容差

如何用 FluentAssertions 替换 Assert.Fail()

使用C#为MSTest测试项目实现自定义断言

在 NAudio 中使用断言

词频统计1.1版——单元测试