Статьи

СУХОЙ: используйте JUnit @Rule вместо повторения установки / @ Before в каждом тесте

В течение долгого времени я был недоволен тем, что   пользователям DbUnit Express приходится создавать метод @Before в каждом тесте только для инициализации тестовой базы данных. К счастью, начиная с версии 1.3.0 им больше не нужно это делать благодаря правилам JUnit  (если вы с ними не знакомы, они являются альтернативой @ Before / @ After и @ BeforeClass / @ AfterClass, прочитайте введение этих правил ) ,

Как настоящие программисты, вы, безусловно, раздражены таким количеством слов, так что давайте перейдем к исходному коду.

Код

Реализация @Rule

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

EmbeddedDbTesterRule (требуется JUnit 4.9+):

public class EmbeddedDbTesterRule extends EmbeddedDbTester implements TestRule {

    private class DbInitializer extends ExternalResource {
        @Override protected void before() throws Throwable {
                EmbeddedDbTesterRule.this.onSetup();
        };
    }

    private final DbInitializer initializer = new DbInitializer();

    /** Ignore - for internal use by JUnit's Rule handling. */
    public final Statement apply(Statement statement, Description description) {
        return initializer.apply(statement, description);
    }
}

Заметки:

  • EmbeddedDbTester — это класс, который используют мои пользователи. Чтобы сделать его самоинициализирующимся, мне нужно было создать подкласс, который реализует TestRule в JUnit.
  • Реализация упрощается путем повторного использования одного из предопределенных правил, ExternalResource , и просто делегирования ему
  • JUnit вызывает метод apply в разное время, из них вызов @Before передается нам через ExternalResource.before . Нам не нужно понимать, что такое «Заявление» или «Описание» и что с ним делать.
  • Точно так же мы могли бы выполнить некоторый код после каждого тестового метода или до / после каждого тестового класса (в этом случае вам нужно будет использовать @ClassRule, я не уверен, как / можно ли его комбинировать с @Rule)

Использование правила в тестовом классе

EmbeddedDbTesterRuleTest :

public class EmbeddedDbTesterRuleTest {

    @Rule public EmbeddedDbTesterRule testDb = new EmbeddedDbTesterRule();

    /**
     * onSetup should have been executed automatically thanks to the @Rule and thus
     * our data should be in the DB.
     */
    @Test
    public void should_execute_onSetup_automatically() throws Exception {
        testDb.createCheckerForSelect("select some_text from my_test_schema.my_test_table")
                .withErrorMessage("No data found => onSetup wasn't executed as expected")
                .assertRowCount(1)
                .assertNext("EmbeddedDbTesterRuleTest data");
    }
}

Заметки:

  • Чтобы использовать его, вы должны объявить открытое нестатическое поле, аннотированное @Rule, а его объявленный тип должен реализовывать TestRule (ранее MethodRule)
  • Затем вы используете экземпляр так же, как и исходный родительский класс ( EmbeddedDbTester ), вам просто не нужно инициализировать его в методе @Before, потому что это делается автоматически

Вывод

@Rules, безусловно, замечательная вещь, которая может упростить жизнь создателям тестов и авторам тестовых фреймворков. Я не очень доволен его API, который мало инвазивен (поле должно быть общедоступным, объявленный тип, а не просто фактическое значение времени выполнения) должен реализовывать TestRule => API моего класса, видимый моим пользователям, изобилует метод, связанный с JUnit), но это все еще довольно хорошая вещь.

Sidenote: О DbUnit Экспресс

Если вы раньше не слышали о DbUnit Express — это тонкая оболочка для DbUnit (модульное тестирование кода, взаимодействующего с базой данных), призванная сделать запуск тестирования БД максимально быстрым и простым, представив

  1. Соглашение о конфигурации — автоматически загружает файл набора данных с именем, полученным из имени теста, если он существует,…
  2. Разумные значения по умолчанию — предварительно настроены для встроенной базы данных Derby
  3. Удобные методы, такие как getDataSource (), чрезвычайно полезны для тестирования кода с использованием Spring JDBC.
  4. Утилиты — RowComparator для простой проверки данных в выборке, DatabaseCreator для инициализации БД из DDL, replaceDatabase (dataSet), clearTable (name), JUnit 4 @Rule, автоматически вызывающий onSetup (),…
  5. Улучшенная отчетность об ошибках
  6. Конфигурация DbUnit, которая оказалась наиболее гибкой и защищенной от ошибок — полностью определенные имена таблиц, набор данных XML,…
  7. Образцы .ddl и набор данных .xml файлов

Для получения дополнительной информации проверьте
домашнюю страницу dbunit-express .

 

От http://theholyjava.wordpress.com/2011/09/04/dry-use-junit-rule-instead-of-repeating-setupbefore-in-each-test/