Есть ли способ заставить JUnit потерпеть неудачу на ЛЮБОМ непроверенном исключении, даже если проглочен - PullRequest
6 голосов
/ 06 мая 2010

Я использую JUnit для написания тестов более высокого уровня для унаследованного кода, который не имеет модульных тестов.

Большая часть этого кода «проглатывает» различные непроверенные исключения, такие как NullPointerExceptions (например, просто печатая трассировку стека и возвращая ноль). Поэтому модульное тестирование может пройти даже сквозь каскад бедствий в различных точках кода нижнего уровня.

Можно ли как-нибудь провалить тест на первом непроверенном исключении, даже если они проглочены?

Единственная альтернатива, о которой я могу подумать, - написать пользовательскую оболочку JUnit, которая перенаправляет System.err и затем анализирует выходные данные на предмет исключений.

Ответы [ 6 ]

4 голосов
/ 06 мая 2010

В отсутствие конкретного решения мой ответ довольно общий:

Такие запахи кода (например, перехватывающие исключения) лучше всего очищать шаг за шагом (класс за классом), когда вы сталкиваетесь с ними при исправлении ошибок в устаревшей системе. Инструменты качества кода (например, Findbugs, PMD, Checkstyle или даже Sonar Quality Server) помогут вам найти эти вещи.

Способ автоматически "ловить" проглоченные исключения - использовать компилятор AspectJ. Вы можете объявить аспекты для генерации ошибки времени компиляции в вашей IDE, когда нарушаются определенные соглашения о коде. В качестве альтернативы вы можете сплести во время выполнения тестируемые классы и позволить AspectJ перебрасывать такие исключения, чтобы они могли записываться бегуном JUnit.

4 голосов
/ 06 мая 2010

Если вы выполняете тесты в отладчике IDE, вы можете настроить IDE так, чтобы он прерывался при возникновении исключения.

1 голос
/ 07 мая 2010

Я бы попытался использовать АОП для сброса ошибок. Нечто подобное должно работать (обратите внимание, я не проверял это, и вам, очевидно, необходимо иметь AspectJ Setup для использования аннотаций 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;

  }

} }

1 голос
/ 06 мая 2010

Я считаю, что Exception - это просто стандартный класс в библиотеках SDK.

Если вы извлекли его, изменили его и поместили где-то на вашем пути к классам до SDK, я думаю, что он должен заменить тот в SDK (Если нет, вы можете поместить свое «новое» исключение обратно в jar SDK) *

В любом случае, ваше новое исключение может установить статическое значение, которое может быть прочитано платформой тестирования.

Возможно, это не самое элегантное решение, но оно не требует никакой "магии"

0 голосов
/ 07 мая 2010

Возможно, вы можете вставить код, который вы пытаетесь проверить. Скорее всего, вам придется использовать некоторые из «переобработанных» сред тестирования, таких как powermock или jmockit, чтобы манипулировать манипулятором загрузчика классов в JVM. Но образец тестируемого класса поможет определить требуемый подход.

0 голосов
/ 06 мая 2010

Может быть возможно смоделировать Исключения, которые вы хотите перехватить, с помощью фреймворка, модифицирующего байт-код, или с помощью фреймворка AOP. Я полагаю, вы могли бы изменить конструктор, чтобы создать более фатальное исключение или установить какой-либо флаг в тестовом коде.

...