有没有办法强制 JUnit 在任何未经检查的异常上失败,即使被吞噬
我正在使用 JUnit 为没有单元测试的遗留代码编写一些更高级别的测试。
大部分代码“吞掉”了各种未经检查的异常,例如 NullPointerException(例如,通过仅打印堆栈跟踪并返回 null)。因此,即使在较低级别代码的各个点上存在一系列灾难,单元测试也可以通过。
有没有什么方法可以让测试在第一个未经检查的异常上失败,即使它们被吞掉了?
我能想到的唯一替代方法是编写一个自定义 JUnit 包装器来重定向 System.err,然后分析输出中的异常。
I am using JUnit to write some higher level tests for legacy code that does not have unit tests.
Much of this code "swallows" a variety of unchecked exceptions like NullPointerExceptions (e.g., by just printing stack trace and returning null). Therefore the unit test can pass even through there is a cascade of disasters at various points in the lower level code.
Is there any way to have a test fail on the first unchecked exception even if they are swallowed?
The only alternative I can think of is to write a custom JUnit wrapper that redirects System.err and then analyzes the output for exceptions.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果您在 IDE 的调试器中执行测试,则可以将 IDE 配置为在引发异常时中断。
If you execute the tests in your IDE's debugger you can configure the IDE to break when an exception is thrown.
由于缺乏具体的解决方案,我的答案非常笼统:
当您在修复遗留系统错误时遇到此类代码气味(例如,swalling 异常)时,最好逐步(逐类)清理它们。代码质量工具(例如 Findbugs、PMD、Checkstyle 甚至 Sonar Quality Server)可以帮助您找到这些东西。
自动“捕获”吞没异常的一种方法是使用 AspectJ 编译器。当违反某些代码约定时,您可以声明方面以在 IDE 中生成编译时错误。或者,您可以在运行时编织被测试的类,并让 AspectJ 重新抛出此类异常,以便 JUnit 运行程序可以记录它们。
In lack of a concrete solution, my answer's pretty general:
Such code smells (e.g. swalling exceptions) are best cleaned up step by step (class by class) when you encounter them while bugfixing the legacy system. Code quality tools (e.g. Findbugs, PMD, Checkstyle or even Sonar Quality Server) help you find those things.
A way to "catch" swallowed exceptions automatically is to use AspectJ compiler. You can declare aspects to generate a compile-time error in your IDE when certain code conventions are violated. Alternatively, you can weave at runtime the classes under test and let AspectJ rethrow such exceptions, so they can be recorded by the JUnit runner.
我相信 Exception 只是 SDK 库中的一个标准类。
如果你提取它,修改它并将其放在 SDK 之前的类路径中的某个位置,我认为它应该替换 SDK 中的那个(如果不是,你可以将你的“新”异常放回到 SDK jar 中)
无论如何,你的新异常可以设置一个可由测试框架读取的静态值。
可能不是最优雅的解决方案,但它不需要任何“魔法”
I believe Exception is just a standard class in the SDK libraries.
If you extracted it, modified it and put it somewhere on your classpath before the SDK, I think it should replace the one in the SDK (If not you could put your "new" exception back into the SDK jar)
Anyway, your new exception could set a static value that can be read by the testing framework.
May not be the most elegant solution but it doesn't require any "Magic"
我会尝试使用 AOP 来抛出失败。像这样的东西应该可以工作(注意,我还没有测试过这个,你显然需要有 AspectJ 设置才能使用 AOP 注释)
}
}
I would try to use AOP to throw failures. Something like this should work (note, I haven't tested this, and you obviouslly need to have AspectJ Setup to use AOP annotations)
}
}
可以使用修改字节码的模拟框架或 AOP 框架来模拟您想要捕获的异常。我想您可以修改构造函数以引发更致命的异常,或者在测试代码中设置一些标志。
It could be possible to mock the Exceptions you want to catch with a mocking framework that modifies the bytecode, or with an AOP framework. I imagine you could modify the constructor to throw a more fatal Exception, or to set some flag in your test code.
也许您可以粘贴您要测试的代码。最有可能的是,您必须使用一些“重新映射器”测试框架(例如 powermock 或 jmockit)来操纵 JVM 中的类加载器操作。但是被测类的样本将有助于确定所需的方法。
Perhaps you can paste the code that you are trying to test. Mostly likely you would have to use some of "remapper" testing frameworks such as powermock or jmockit to manipulate the classloader manipulation in JVM. But a sample of class under test would help determine the approach required.