如果我们已经创建了一个单例对象来处理 Java 异常,为什么 Thread.setDefaultUncaughtExceptionHandler 在 Java 应用程序服务器、Java 控制台应用程序中运行正常,但在 JUnit 测试中却不起作用?
例如,下面的代码有效:
public class Main extends Object {
public static void main(String[] arguments) {
Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler.getInstance());
double a = 1/0;
}
}
但是这个 JUnit 测试不是:
public class UncaughtExceptionHandlerTest {
@Test
public void throwException() {
Thread.setDefaultUncaughtExceptionHandler(UncaughtExceptionHandler.getInstance());
double a = 1/0;
}
}
但是为什么?而且,我们如何解决这个问题,以自动处理所有 JUnit 测试异常,而无需对每个测试使用喜怒无常的 try catch?
最佳答案
JUnit 将捕获单元测试线程1 上的单元测试抛出的所有 意外异常。正常行为是将异常捕获/显示/记录为 FAILed 测试,然后继续下一个单元测试。
这意味着在 Java 意义上不存在“未捕获的异常”,并且您的未捕获的异常处理程序不会被调用。
目前还不完全清楚您要在这里实现什么,但我怀疑答案是实现自定义运行器:
1 - 如果被测代码生成自己的线程,JUnit 框架无法知道。它肯定不能捕获/检测那些线程上未捕获的异常。但是,这似乎不是您在这个问题中谈论的内容。
The main motivation, is, for example, send an e-mail or perform another administrative tasks if a junit test fail. If I have a global exception handler I could do this, instead put a catch block to each test. After the handling, maybe I will throw this exception and let junit go ahead as it does.
好吧,如果那是您想要做的,那么您 (IMO) 做错了。现有的运行程序提供结构化报告文件或报告数据结构,可以为您提供所有通过的测试、因断言失败、因异常失败等的列表。您应该做的是:
- 选择合适的运行者
- 分析其输出
- 如果出现符合您标准的错误,请发送一封电子邮件(或其他任何邮件)。
优点:
- 更省力
- 您处理所有错误,而不仅仅是未捕获的异常(尽管实际上断言失败表现为
AssertionError
异常 ...) - 您不会在每次失败的测试中都向自己发送垃圾邮件。
还有另一种方法。查看 JUnitCore
( link )。这允许您为各种测试事件注册一个监听器,然后运行一堆测试或测试套件。
另一点是,您似乎在尝试复制(部分)持续集成 (CI) 服务器(例如 Jenkins)的功能。
然后你问为什么这不起作用:
@Test
public void throwException() {
Thread.setDefaultUncaughtExceptionHandler(/* some handler */));
double a = 1/0;
}
未捕获的异常处理程序只有在没有其他任何东西捕获到异常时才会被调用。但是,典型的 JUnit 测试运行程序使用传统的异常处理程序捕获从每个单元测试传播的所有异常。这意味着在您的测试中抛出的 ArithmeticException
永远不会到达您的处理程序。
关于java - 如何在 junit 测试中捕获所有未捕获的异常?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36648317/