有没有办法验证使用 JUnit 时是否在测试方法中调用了 try/catch 指令的 Catch 部分?

Is there a way to verify if the Catch part of a try/catch instruction is called in a test method when using JUnit?

例如,如果我要测试以下 class:

public class SomeClass{
    public void someMethod() {
        try {
            //Some code, where comething could go wrong
        } catch (Exception err) {
            //Handling it amounts to logging the problem and trying to continue
        }
    }
 }

如果我随后使用 JUnit 测试此方法,那么如果 try 子句中出现问题并且捕获代码为 运行,则测试将通过。

我想这样做,如果 catch 子句指令是 运行.

,测试就会失败

我确实想到了一些我可以尝试编写测试的方法,以便我获得等效的功能,但是每种方法都有我不想那样做的原因。如果达到任何 catch 子句,似乎试图使测试失败是最干净的方法,如果这实际上是可能的话

备注:

我知道我可以验证代码的某些功能并检查它们是否是某些 value/have 已经 运行 使用 Mockito 多次。但是,我想要一个解决方案,如果对测试方法进行了更改,从根本上改变了它的工作方式(但不是本质上正在执行的任务),那么我就不必重写测试了。

不幸的是,为了使这个问题更加困难,我无法对源代码进行任何修改。这个职位是我无法控制的,所以我必须在这些范围内工作。


编辑:

SomeClass 是我要测试的 class。它不是实际的 JUnit 测试。我已经编辑了我的原始问题以尝试澄清这一点。

我以前遇到过这种问题。我最终模拟了日志子系统(不简单但不过分复杂)并监听了 'interesting' 日志调用,然后在它发生时标记失败。

您可以考虑使用 assert

什么是断言你可能会问:

An assertion is a statement in the JavaTM programming language that enables you to test your assumptions about your program. For example, if you write a method that calculates the speed of a particle, you might assert that the calculated speed is less than the speed of light.

我没有详细介绍,因为我无法比它自己的文档更好地解释它。

请记住,您正在测试此函数的行为。你的测试不应该关心(所以不测试)异常被捕获,只关心你想要的行为发生。

这意味着如果您想测试是否记录了某些内容(或未记录)。然后你必须验证一些东西被记录了。在我的几个应用程序中,我区分了调试日志记录和重要日志消息。后者我们通过 class 发送(在我们的例子中我们使用了 Facade 设计模式)。我们可以模拟(从而测试调用)。对于大多数应用程序,许多开发人员日志记录不必进行测试,因此在这些情况下您应该忽略它。

我不知道有任何框架可以让您断言异常已在方法中抛出和处理并且未传播。从问题描述中我会看到两种方法,都使用 BDD:

  1. 断言未调用 catch 块内的一行代码 - 正如@Thirler 建议的那样,记录器将是一个不错的选择
  2. 断言未调用异常构造函数

两者都有问题:

  1. 不像您希望的那样干净,因为它与正在执行的实际代码紧密耦合。
  2. 代码中处理的任何异常都会触发失败。

您可以尝试使用 aspectj 检测代码并标记在执行 SomeClass.someMethod 时抛出异常。

一般来说,

-1- 检查某个函数 f() 是否抛出异常

try {
  f();
  // notify test failure here
} catch (...) {
  // success
};

-2- 检查它没有

try {
   f();
} catch(...) {
   // notify test failure here
}