有没有办法强制JUnit在任何未经检查的异常上失败,即使被吞下也是如此

时间:2010-05-06 17:13:43

标签: java unit-testing junit swallowed-exceptions

我正在使用JUnit为没有单元测试的遗留代码编写一些更高级别的测试。

这些代码中的大部分都“吞噬”了各种未经检查的异常,例如NullPointerExceptions(例如,只打印堆栈跟踪并返回null)。因此,即使在较低级别的代码中的各个点存在一连串的灾难,单元测试也可以通过。

有没有办法让第一个未经检查的异常测试失败,即使它们被吞下了?

我能想到的唯一选择是编写一个自定义JUnit包装器,重定向System.err,然后分析输出异常。

6 个答案:

答案 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中的类加载器操作。但是,受测试的课程样本将有助于确定所需的方法。