Встроенные Postgres для весенних тестов загрузки
Я создаю приложение Spring Boot, поддерживаемое Postgres, используя Flyway для миграции баз данных. Я столкнулся с проблемами, когда я не могу выполнить миграцию, которая генерирует желаемый результат как в Postgres, так и в базе данных встроенных модулей (даже если включен режим совместимости Postgres). Поэтому я рассматриваю использование встроенных Postgres для модульных тестов.
Я столкнулся с внедренной реализацией postgres, которая выглядит многообещающей, но на самом деле не вижу, как настроить ее для запуска только в рамках тестовой платформы Spring Boot (для тестирования хранилищ Spring Data). Как бы установить это с помощью упомянутого инструмента или альтернативной встроенной версии Postgres?
Ответы
Ответ 1
Я являюсь автором встроенной библиотеки database-spring-test, о которой упоминал @MartinVolejnik. Я думаю, что библиотека должна отвечать всем вашим требованиям (PostgreSQL + Spring Boot + Flyway + интеграционное тестирование). Мне очень жаль, что у вас возникли проблемы, поэтому я создал простое демонстрационное приложение, которое демонстрирует использование библиотеки вместе со средой Spring Boot. Ниже я кратко изложил основные шаги, которые вам нужно сделать.
Конфигурация Maven
Добавьте следующую зависимость maven:
<dependency>
<groupId>io.zonky.test</groupId>
<artifactId>embedded-database-spring-test</artifactId>
<version>1.5.0</version>
<scope>test</scope>
</dependency>
Конфигурация Flyway
Добавьте следующее свойство в конфигурацию вашего приложения:
# Sets the schemas managed by Flyway -> change the xxx value to the name of your schema
# flyway.schemas=xxx // for spring boot 1.x.x
spring.flyway.schemas=xxx // for spring boot 2.x.x
Кроме того, убедитесь, что вы не используете org.flywaydb.test.junit.FlywayTestExecutionListener
. Поскольку библиотека имеет свой собственный прослушиватель выполнения теста, который может оптимизировать инициализацию базы данных, и эта оптимизация не имеет никакого эффекта, если применяется FlywayTestExecutionListener
.
Конфигурация Spring Boot 2
Начиная с Spring Boot 2, существует проблема совместимости с Hibernate и Postgres Driver. Поэтому вам может потребоваться добавить следующее свойство в конфигурацию приложения, чтобы это исправить:
# Workaround for a compatibility issue of Spring Boot 2 with Hibernate and Postgres Driver
# See https://github.com/spring-projects/spring-boot/issues/12007
spring.jpa.properties.hibernate.jdbc.lob.non_contextual_creation=true
пример
Пример тестового класса, демонстрирующий использование встроенной базы данных:
@RunWith(SpringRunner.class)
@DataJpaTest
@AutoConfigureEmbeddedDatabase
public class SpringDataJpaAnnotationTest {
@Autowired
private PersonRepository personRepository;
@Test
public void testEmbeddedDatabase() {
Optional<Person> personOptional = personRepository.findById(1L);
assertThat(personOptional).hasValueSatisfying(person -> {
assertThat(person.getId()).isNotNull();
assertThat(person.getFirstName()).isEqualTo("Dave");
assertThat(person.getLastName()).isEqualTo("Syer");
});
}
}
Ответ 2
Конфигурация ниже хорошо работает с Spring Boot 2.0.
Преимущество теста embedded-database-spring-test заключается в том, что это решение не переносит Flyway в путь к классам, возможно, испортив автоконфигурацию Spring Boot.
@Configuration
@Slf4j
public class EmbeddedPostgresConfiguration {
@Bean(destroyMethod = "stop")
public PostgresProcess postgresProcess() throws IOException {
log.info("Starting embedded Postgres");
String tempDir = System.getProperty("java.io.tmpdir");
String dataDir = tempDir + "/database_for_tests";
String binariesDir = System.getProperty("java.io.tmpdir") + "/postgres_binaries";
PostgresConfig postgresConfig = new PostgresConfig(
Version.V10_3,
new AbstractPostgresConfig.Net("localhost", Network.getFreeServerPort()),
new AbstractPostgresConfig.Storage("database_for_tests", dataDir),
new AbstractPostgresConfig.Timeout(60_000),
new AbstractPostgresConfig.Credentials("bob", "ninja")
);
PostgresStarter<PostgresExecutable, PostgresProcess> runtime =
PostgresStarter.getInstance(EmbeddedPostgres.cachedRuntimeConfig(Paths.get(binariesDir)));
PostgresExecutable exec = runtime.prepare(postgresConfig);
PostgresProcess process = exec.start();
return process;
}
@Bean(destroyMethod = "close")
@DependsOn("postgresProcess")
DataSource dataSource(PostgresProcess postgresProcess) {
PostgresConfig postgresConfig = postgresProcess.getConfig();
val config = new HikariConfig();
config.setUsername(postgresConfig.credentials().username());
config.setPassword(postgresConfig.credentials().password());
config.setJdbcUrl("jdbc:postgresql://localhost:" + postgresConfig.net().port() + "/" + postgresConfig.storage().dbName());
return new HikariDataSource(config);
}
}
Maven:
<dependency>
<groupId>ru.yandex.qatools.embed</groupId>
<artifactId>postgresql-embedded</artifactId>
<version>2.9</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
Класс основан на коде, который я нашел здесь: https://github.com/nkoder/postgresql-embedded-example
Я изменил его, чтобы использовать HikariDatasource
(Spring Boot default) для правильного объединения пулов. binariesDir
и dataDir
используются, чтобы избежать дорогостоящей экстракции + initdb в повторных испытаниях.
Ответ 3
Взгляните на это: https://github.com/zonkyio/embedded-database-spring-test. Чтобы быть понятным, это означало интеграционное тестирование. Значение контекста Spring инициализируется во время индивидуального теста.
В соответствии с документацией по инструментам все, что вам нужно сделать, это разместить аннотацию @AutoConfigureEmbeddedDatabase
выше класса:
@RunWith(SpringRunner.class)
@AutoConfigureEmbeddedDatabase
@ContextConfiguration("/path/to/app-config.xml")
public class FlywayMigrationIntegrationTest {
@Test
@FlywayTest(locationsForMigrate = "test/db/migration")
public void testMethod() {
// method body...
}
}
и добавьте зависимость Maven:
<dependency>
<groupId>io.zonky.test</groupId>
<artifactId>embedded-database-spring-test</artifactId>
<version>1.1.0</version>
<scope>test</scope>
</dependency>
Чтобы использовать его вместе с @DataJpaTest
вам необходимо отключить тестовую базу данных по умолчанию, используя аннотацию @AutoConfigureTestDatabase(replace = NONE)
:
@RunWith(SpringRunner.class)
@AutoConfigureTestDatabase(replace = NONE)
@AutoConfigureEmbeddedDatabase
@DataJpaTest
public class SpringDataJpaTest {
// class body...
}
Чтобы сделать использование более удобным, вы также можете создать составную аннотацию, например:
@Documented
@Inherited
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@AutoConfigureTestDatabase(replace = NONE)
@AutoConfigureEmbeddedDatabase
@DataJpaTest
public @interface PostgresDataJpaTest {
}
.. и затем используйте его над вашим тестовым классом:
@RunWith(SpringRunner.class)
@PostgresDataJpaTest // custom composite annotation
public class SpringDataJpaTest {
// class body...
}
Ответ 4
Вы можете попробовать https://github.com/TouK/dockds. Это автоматически настраивает базу данных, содержащую докеры.