Запуск пользовательского расширения JUnit 5 перед аннотацией @Sql в интеграционном тесте Spring Boot

#spring #spring-boot #spring-test

Вопрос:

Я аннотировал интеграционный тест Spring Boot @Sql для настройки тестовых данных в базе данных, который работает просто отлично.

 @Test
@DisplayName("Should add message to user's inbox")
@Sql(scripts = "classpath:/sql/init.sql")
public void should_add_message() {
    // test logic...
}
 

Однако я хотел бы иметь пустую базу данных для каждого интеграционного теста, поэтому я добавил расширение JUnit 5, которое удаляет каждую строку из каждой таблицы. Регистрация этого расширения происходит с @ExtendWith(DatabaseCleanerExtension.class) помощью .

 public class DatabaseCleanerExtension implements BeforeEachCallback {

    @Override
    public void beforeEach(ExtensionContext extensionContext) throws Exception {
        final DataSource dataSource = SpringExtension.getApplicationContext(extensionContext).getBean(DataSource.class);
        final Connection connection = dataSource.getConnection();

        final ResultSet resultSet = connection.getMetaData().getTables(null, null, null, new String[]{"TABLE"});

        connection.prepareStatement("SET FOREIGN_KEY_CHECKS = 0").execute();
        while (resultSet.next()) {
            connection.prepareStatement("DELETE FROM "   resultSet.getString("TABLE_NAME")).execute();
        }
        connection.prepareStatement("SET FOREIGN_KEY_CHECKS = 1").execute();
    }
}
 

В то время как само расширение работает и делает то, что я хочу, чтобы оно делало, есть одна серьезная проблема. Очистка базы данных происходит сразу после того, как были вставлены тестовые данные @Sql . Это приводит к тому, что база данных снова пуста.

Есть ли способ запустить это расширение до @Sql аннотации? Мой первый обходной путь-это переход на a AfterEachCallback , но, может быть, есть какой-то другой подход?


Обновление 1

Моя тестовая установка уже использует проект Testcontainers для запуска экземпляра базы данных. Я использую шаблон одноэлементного контейнера, как описано здесь, чтобы избежать ненужных перезапусков между тестами. Вот почему я хотел бы сбросить таблицы базы данных.

Комментарии:

1. А как насчет использования @TestInstance(Lifecycle.PER_CLASS) ? Фреймворк Testcontainers также может быть вариантом/на который приятно посмотреть.