我正在使用JUnit为没有单元测试的遗留代码编写一些更高级别的测试。
这些代码中的大部分都“吞噬”了各种未经检查的异常,例如NullPointerExceptions(例如,只打印堆栈跟踪并返回null)。因此,即使在较低级别的代码中的各个点存在一连串的灾难,单元测试也可以通过。
有没有办法让第一个未经检查的异常测试失败,即使它们被吞下了?
我能想到的唯一选择是编写一个自定义JUnit包装器,重定向System.err,然后分析输出异常。
答案 0 :(得分:4)
如果在IDE的调试器中执行测试,则可以将IDE配置为在抛出异常时中断。
答案 1 :(得分:4)
由于缺乏具体的解决方案,我的回答非常普遍:
这样的代码气味(例如,swalling异常)最好在你修复遗留系统时遇到它们时逐步清理(逐类)。代码质量工具(例如Findbugs,PMD,Checkstyle甚至Sonar Quality Server)可以帮助您找到这些东西。
自动“捕获”吞噬异常的一种方法是使用AspectJ编译器。当违反某些代码约定时,您可以声明方面以在IDE中生成编译时错误。或者,您可以在运行时编织测试中的类,并让AspectJ重新抛出这些异常,这样它们就可以由JUnit运行器记录。
答案 2 :(得分:1)
我相信Exception只是SDK库中的标准类。
如果你解压缩它,修改它并把它放在SDK之前的类路径上,我认为应该替换SDK中的那个(如果不是你可以将你的“新”异常放回SDK jar中)
无论如何,您的新异常可以设置一个可以由测试框架读取的静态值。
可能不是最优雅的解决方案,但它不需要任何“魔术”
答案 3 :(得分:1)
我会尝试使用AOP来引发失败。这样的东西应该工作(注意,我没有测试过这个,你显然需要让AspectJ设置使用AOP注释)
public class ClassUnderTest
{
private static Boolean exceptionThrown;
@Before
public void resetExceptionFlag()
{
ClassUnderTest.exceptionThrown = false;
}
@Test
public void myTestMethod()
{
//....
// My Test Exception Code
//....
assertFalse(ClassUnderTest.exceptionThrown);
}
@Aspect
static class TestAspects
{
@Pointcut("handler(Exception)")
public void intereceptAllExceptions(){}
//This is Fully Qualified because of the conflict with the junit Before annotation above
@org.aspectj.lang.annotation.Before("intereceptAllExceptions()")
public void flagExceptionThrown()
{
ClassUnderTest.exceptionThrown = true;
}
} }
答案 4 :(得分:0)
可以使用修改字节码的模拟框架或使用AOP框架来模拟要捕获的异常。我想你可以修改构造函数以抛出更致命的异常,或者在测试代码中设置一些标志。
答案 5 :(得分:0)
也许您可以粘贴您要测试的代码。很可能你必须使用一些“重映射”测试框架,如powermock或jmockit来操作JVM中的类加载器操作。但是,受测试的课程样本将有助于确定所需的方法。