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