【问题标题】:Asserting against handled exceptions in NUnit断言在 NUnit 中处理的异常
【发布时间】:2019-11-21 08:20:29
【问题描述】:

我有一个方法,它接受一个 JSON 对象并对其进行多个处理阶段,在每个阶段更新数据库中的值。我们希望此方法具有容错性,并决定所需的行为是,如果任何处理阶段失败,则将错误记录到数据库并继续下一个处理阶段,而不是中止。

我刚刚对其中一个处理步骤的行为进行了几处更改。然后我运行了我们的单元测试套件,预计有几个测试会由于新行为而失败,并指出潜在的问题区域。相反,测试都通过了。

经过调查,我意识到运行测试的模拟数据不包含对新行为很重要的某些关键值。测试实际上在运行时抛出异常,但异常被捕获和处理 - 而且,因为测试没有在启用记录器的情况下运行,所以它们被完全抑制。因此,新代码不会以会导致测试失败的方式更改数据,因为它会默默地出错。

这似乎是单元测试要解决的问题,而它们没有显示任何痕迹的事实意味着它们没有达到目的。有什么方法可以使用 NUnit 断言没有抛出异常,即使它已被处理?或者,是否有一种明智的重构方法可以更好地暴露这个问题?

(在 C# 中工作,但问题似乎与语言无关)

【问题讨论】:

  • 并非如此,测试函数的行为在更改前后(就调用者而言)保持不变,因此所有测试都通过了。如果你引入了新的副作用,你也应该编写单元测试。在您的情况下,我想测试错误日志记录很困难,但我想既然您可以预测执行路径,您就知道 logger 将被调用多少次,因此您可以使用一些模拟记录器并断言模拟记录器被称为预期数量次。
  • 你的类的预期行为是它应该捕获某些异常并记录它们。您无法测试捕获异常。您只能测试一个类的作用——它返回的结果、状态的变化以及它引起的影响。在这种情况下,您要测试代码产生的效果,并将其输出到日志中。这意味着您必须模拟日志。它可以像创建将消息添加到列表的日志实现一样简单。如果您包含一些代码来显示您如何调用记录器(是否已注入),那么我们可以提供更多详细信息。
  • 它被注入了,我刚刚使用 NSubstitute 创建了一个 subbed 记录器,每当调用它的 LogError 函数时都会引发异常,现在我的大部分测试都失败了!感谢您的建议!

标签: c# unit-testing exception nunit


【解决方案1】:

首先,在您描述的场景中,是否存在异常是次要的。如果您编写代码以在捕获和处理异常的同时产生所需的结果,那么该结果 - 无论是返回值还是其他效果 - 都是最重要的测试。

如果您没有看到的异常导致该结果不正确,那么测试正确结果将始终揭示问题。如果您不知道预期的结果是什么,并且只对异常是否得到处理感兴趣,那么就有问题了。我们永远无法根据它是否抛出异常来确定任何东西是否正常工作。

除此之外,以下是测试您的代码是否正在捕获和记录您原本无法观察到的异常的方法:

如果您要注入如下所示的记录器:

public interface ILogger
{
    void LogError(Exception ex);
    void LogMessage(string message);
}

...那么一个简单的方法是创建一个存储异常的测试替身,以便您可以检查它并查看记录的内容。

public class ListLoggerDouble : ILogger
{
    public List<Exception> Exceptions = new List<Exception>();
    public List<string> Messages = new List<string>();

    public void LogError(Exception ex)
    {
        Exceptions.Add(ex);
    }

    public void LogMessage(string message)
    {
        Messages.Add(message);
    }
}

在您执行了您正在测试的方法之后,您可以断言集合包含您期望的异常或消息。如果你希望你也可以验证没有,尽管如果你测试的结果是正确的,这似乎是多余的。


我不会创建一个引发异常的记录器,然后编写一个测试来检查引发的异常。这使得代码的预期行为看起来像是抛出异常,这与它的作用完全相反。测试帮助我们记录预期的行为。另外,如果您想验证是否捕获并记录了两个异常,您会怎么做?

【讨论】:

  • 更重要的是我创建了一个记录器,如果抛出异常会引发异常导致测试失败,因为这些测试不应该引发异常
  • 我明白了。但结果是您有一个在正常情况下不会抛出异常的类,以及一个断言它确实抛出异常的测试。同时,类的实际预期行为 - 它记录异常 - 测试。
猜你喜欢
  • 2013-03-16
  • 2012-08-15
  • 1970-01-01
  • 1970-01-01
  • 2019-05-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多