2015-09-03 1 views
4

Согласно the 4.12 release notes, можно аннотировать статические члены тестового класса как с @Rule и @ClassRule:Как совместить @Rule и @ClassRule в JUnit 4,12

статический член с аннотацией как @ Правило и @ClassRule теперь считаются действительными. Это означает, что для выполнения действий как до, так и после класса может использоваться одно правило (например, установка/отключение внешнего ресурса) и между тестами (например, сброс внешнего ресурса),

Я хочу использовать эту функциональность для инициализации ресурса в начале всех тестов в файле, выполните некоторую очистку на ресурсе между каждым тестом и утилизируйте его после завершения всех тестов. Этот ресурс в настоящее время представлен классом, который расширяет ExternalResource.

В моих методах before и after, как я могу различать «до/после всех тестов» и «до/после каждого теста»? Нужно ли использовать другую/пользовательскую реализацию TestRule, чтобы выполнить это?

+0

[Вот статья, которая объясняет правила JUnit] (HTTP : //www.singhajit.com/junit-rules/) –

+0

@AjitSingh в этой статье не объясняется, как комбинировать поведение @ Rule и @ ClassRule в одном классе, реализующем TestRule. – martiansnoop

ответ

1

Вы можете реализовать TestRule#apply и использовать isTest и isSuite методы Description, чтобы определить, какой Statement ваш TestRule прикладывается к.

Вот пример интерфейса можно создать, чтобы дать правило, которое имеет полный before, after, verify, beforeClass, afterClass, verifyClass тип поведения:

public interface CombinedRule extends TestRule { 
    default Statement apply(Statement base, Description description) { 
     if (description.isTest()) { 
      return new Statement() { 
       public void evaluate() throws Throwable { 
        before(); 
        try { 
         base.evaluate(); 
         verify(); 
        } finally { 
         after(); 
        } 
       } 
      }; 
     } 
     if (description.isSuite()) { 
      return new Statement() { 
       public void evaluate() throws Throwable { 
        beforeClass(); 
        try { 
         base.evaluate(); 
         verifyClass(); 
        } finally { 
         afterClass(); 
        } 
       } 
      }; 
     } 
     return base; 
    } 

    default void before() throws Exception { 
     //let the implementer decide whether this method is useful to implement 
    } 

    default void after() { 
     //let the implementer decide whether this method is useful to implement 
    } 

    /** 
    * Only runs for Tests that pass 
    */ 
    default void verify() { 
     //let the implementer decide whether this method is useful to implement 
    } 

    default void beforeClass() throws Exception { 
     before(); 
    } 

    default void afterClass() { 
     after(); 
    } 

    /** 
    * Only runs for Suites that pass 
    */ 
    default void verifyClass() { 
     verify(); 
    } 
} 
0

методы аннотированные с @Before и @After будет работать до и после каждого испытания, в то время как те, с аннотацией @BeforeClass и @AfterClass будет работать до и после первого/последнего теста в классе соответственно.

Методы до/после @Rule выполняются до и после каждого теста, в то время как методы до и после @ClassRule выполняются до/после всего тестового класса.

Вы можете использовать ExternalResource для случая @Rule или @ClassRule, если методы обработчика должным образом реагируют на оба сценария. Насколько я могу судить по документации, нет никаких средств для разграничения между двумя категориями правил в методах класса правил. Если вы используете класс правил для обоих случаев, он будет применяться одинаково для обоих.

+0

Итак, если @ClassRule и @Rule находятся на одном и том же статическом члене, методы 'before' /' after' будут выполняться до/после всего класса * и * до/после каждого теста?Это не кажется полезным, поскольку он не проводит различия между дорогостоящей настройкой и отключением ресурса и сбросом (без полного разрыва) между испытаниями. Вы знаете, почему команда юнита решила, что это было полезно? Является ли ответ использовать отдельные члены @Rule и @ClassRule, например, в блоге, который вы связали? – martiansnoop

+0

Я бы предположил, что кто-то придумал действительный прецедент, поэтому они внедрили его. Было бы неплохо, если бы они указали на этот случай. :-) Да, я бы предложил расщепить их, как в моей записи в блоге (http://coffeaelectronica.com/blog/2013/junit-rules.html) – cjstehno

0

Нельзя проводить различие между @BeforeClass и @Before или @AfterClass и @After. Более подробную информацию о причине добавления этой функции можно найти в pull request.

0

Вы можете создать собственное правило, реализующий как TestRule и MethodRule:

public SharableExternalResource implements TestRule, MethodRule { 

    public final Statement apply(
     final Statement base, Description description) { 
    return 
     new Statement() { 
      @Override 
      public void evaluate() throws Throwable { 
      beforeClass(); 

      List<Throwable> errors = new ArrayList<Throwable>(); 
      try { 
       base.evaluate(); 
      } catch (Throwable t) { 
       errors.add(t); 
      } finally { 
       try { 
        afterClass(); 
       } catch (Throwable t) { 
        errors.add(t); 
       } 
      } 
      MultipleFailureException.assertEmpty(errors); 
      } 
     }; 
    } 

    public final Statement apply(
     Statement base, FrameworkMethod method, Object target) { 
    return 
     new Statement() { 
      @Override 
      public void evaluate() throws Throwable { 
      before(); 

      List<Throwable> errors = new ArrayList<Throwable>(); 
      try { 
       base.evaluate(); 
      } catch (Throwable t) { 
       errors.add(t); 
      } finally { 
       try { 
        after(); 
       } catch (Throwable t) { 
        errors.add(t); 
       } 
      } 
      MultipleFailureException.assertEmpty(errors); 
      } 
     }; 
    } 

    public void beforeClass() throws Exception { 
    // do nothing 
    } 

    protected void before() throws Exception { 
    // do nothing 
    } 

    protected void after() throws Exception { 
    // do nothing 
    } 

    public void afterClass() throws Exception { 
    // do nothing 
    } 
} 
+0

Документация для состояний MethodRule «Обратите внимание, что MethodRule был заменен TestRule , который имеет дополнительное преимущество в поддержке правил класса », что, по-видимому, означает, что MethodRule устарел в пользу TestRule. Я не запускал ваш код, поэтому я не могу сказать точно, но кажется странным, что TestRule игнорирует аннотацию @Rule, если рассматриваемое правило также реализует MethodRule. – martiansnoop

 Смежные вопросы

  • Нет связанных вопросов^_^