Подтвердить что ты не робот

Как заполнить базу данных только один раз перед методами @Test в тесте spring?

Следующим тестовым тестированием spring уровня сервиса с junit4 является: Как вызвать script, который заполняет базу данных только один раз перед всеми методами @Test: Я хочу выполнить это один раз перед всеми @Tests:

JdbcTestUtils.executeSqlScript(jdbcTemplate(), new FileSystemResource(
"src/main/resources/sql/mysql/javahelp-insert.sql"), false);

Я попытался использовать @PostConstruct в моем классе GenericServiceTest (расширенный тестовыми классами). Оказалось, что @PostConstruct вызывается каждый раз перед каждым методом @Test. Интересно, что даже любые методы, аннотированные @Autowired из GenericServiceTest, вызывается перед каждым методом @Test.

Я не хочу заполнять базу данных перед каждым тестовым классом, но только один раз при запуске spring -test.

Как выполнить вышеописанный метод только один раз перед всеми методами @Test с помощью spring рамки тестирования и junit4?

Спасибо!

4b9b3361

Ответ 1

Использование поддержки встроенных баз данных Springs

<jdbc:embedded-database id="dataSource">
    <jdbc:script location="classpath:myScript.sql"/>
    <jdbc:script location="classpath:otherScript.sql"/>
</jdbc:embedded-database>

или Springs Инициализировать поддержку базы данных

<jdbc:initialize-database data-source="dataSource">
    <jdbc:script location="classpath:myScript.sql"/>
    <jdbc:script location="classpath:otherScript.sql"/>
</jdbc:initialize-database>

@See http://static.springsource.org/spring/docs/3.0.x/spring-framework-reference/html/jdbc.html#jdbc-embedded-database-support

Ответ 2

Основываясь на ответе Альфредоса, это способ ввода информации о базе данных без вызова встроенной базы данных по умолчанию script. Например, это может быть полезно, когда вы хотите автоматическую сборку DDL для вас - по крайней мере, в тестах.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"/applicationContext.xml"})
public class TestClass {

    @Autowired
    private ApplicationContext ctx;

    private JdbcTemplate template;

    @Autowired
    public void setDataSource(DataSource dataSource) {
       template = new JdbcTemplate(dataSource);
    }

    private static boolean isInitialized = false;

    @Before
    public void runOnce() {
        if (isInitialized) return;
        System.out.println("Initializing database");

        String script = "classpath:script.sql"; 
        Resource resource = ctx.getResource(script);
        JdbcTestUtils.executeSqlScript(template, resource, true);            
        isInitialized = true;
    }
}

Таким образом, метод runOnce() вызывается один раз и только один раз для тестового прогона. Если вы сделаете isInitialized поле экземпляра (нестатического), метод будет вызываться перед каждым тестом. Таким образом, вы можете сбросить/повторно заполнить таблицы, если необходимо, перед каждым испытанием.

Обратите внимание, что это по-прежнему довольно быстрое и грязное решение, и разумный способ обработки базы данных соответствует ответу Ральфа.

Ответ 3

Если вы используете Spring Boot, вы можете указать несколько скриптов для запуска перед тестированием через

spring.datasource.data=classpath:accounts.sql, classpath:books.sql, classpath:reviews.sql

Ответ 4

Пример, основанный на примере Майка Адлерса, но для JUnit 5 и с использованием ResourceDatabasePopulator, упомянутым Tugdual.

Тестовые классы создаются один раз для каждого метода тестирования. Так что если вы хотите заполнить только один раз, вам нужно как-то справиться с этим. Здесь это делается с помощью статической переменной.

@Autowired
private DataSource dataSource;

private static boolean isInitialized;

@BeforeEach // JUnit 5
void initDatabase() {
  if(!isInitialized) { // init only once
    ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
    populator.addScript(new ClassPathResource("/sql/myscript.sql")));
    populator.execute(dataSource);
    isInitialized = true;
  }
}