Как протестировать приложение Spring Boot с несколькими контейнерами MariaDB?JAVA

Программисты JAVA общаются здесь
Ответить
Anonymous
 Как протестировать приложение Spring Boot с несколькими контейнерами MariaDB?

Сообщение Anonymous »

Я разрабатываю приложение Spring Boot, которое использует глобальную базу данных и локальную базу данных (одна БД, две схемы). Вот текущая конфигурация базы данных, которая отлично работает с приложением (я отправляю только локальную конфигурацию, глобальная такая же, но, очевидно, с другими пакетами и именами):

Код: Выделить всё

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
basePackages = "com.myapp.local",
entityManagerFactoryRef = "localEntityManagerFactory",
transactionManagerRef = "localTransactionManager"
)
public class LocalDbConfig {

@Value("${spring.datasource.local.url}")
private String url;

@Value("${spring.datasource.local.username}")
private String username;

@Value("${spring.datasource.local.password}")
private String password;

@Value("${spring.datasource.local.driver-class-name}")
private String driverClassName;

@Primary
@Bean(name = "localDbDataSource")
public DataSource localDbDataSource() {
return DataSourceBuilder.create()
.url(url)
.username(username)
.password(password)
.driverClassName(driverClassName)
.build();
}

@Primary
@Bean(name = "localEntityManagerFactory")
public LocalContainerEntityManagerFactoryBean localEntityManagerFactory(EntityManagerFactoryBuilder builder, @Qualifier("localDbDataSource") DataSource localDataSource) {
Map props = new HashMap();
props.put("hibernate.physical_naming_strategy", CamelCaseToUnderscoresNamingStrategy.class.getName());
return builder
.dataSource(localDataSource)
.packages("com.myapp.local")
.properties(props)
.build();
}

@Primary
@Bean(name = "localTransactionManager")
public PlatformTransactionManager localTransactionManager(@Qualifier("localEntityManagerFactory") EntityManagerFactory localEntityManagerFactory) {
return new JpaTransactionManager(localEntityManagerFactory);
}
}
Я хочу протестировать приложение, используя два успешно запустившихся контейнера MariaDB. Однако оба контейнера останавливаются со следующей ошибкой:
"Ожидание подключения к базе данных по адресу jdbc:mysql://x.x.x.x:xxxx/test с использованием запроса "SELECT 1"
Это мой TestContainersInitializer:

Код: Выделить всё

@TestConfiguration
public class TestContainersInitializer implements ApplicationContextInitializer {

private static final Network SHARED_NETWORK = Network.newNetwork();

private static final MariaDBContainer localMariaDB = new MariaDBContainer(DockerImageName.parse("mariadb:latest"))
.withNetwork(SHARED_NETWORK)
.withDatabaseName("local_db")
.withUsername("root")
.withPassword("test")
.withReuse(true);

private static final MariaDBContainer globalMariaDB = new MariaDBContainer(DockerImageName.parse("mariadb:latest"))
.withNetwork(SHARED_NETWORK)
.withDatabaseName("global_db")
.withUsername("root")
.withPassword("test")
.withReuse(true);

private static final KeycloakContainer keycloak = new KeycloakContainer()
.withNetwork(SHARED_NETWORK)
.withRealmImportFile("test-realm-export.json")
.withAdminUsername("keycloakadmin")
.withAdminPassword("keycloakadmin")
.withReuse(true);

private static final KafkaContainer kafka = new KafkaContainer(DockerImageName.parse("confluentinc/cp-kafka:latest"))
.withNetwork(SHARED_NETWORK)
.withReuse(true);

static {
Startables.deepStart(localMariaDB, globalMariaDB, keycloak, kafka).join();

}

@Override
public void initialize(@NotNull ConfigurableApplicationContext applicationContext) {
TestPropertyValues.of(
"spring.datasource.local.url=" + localMariaDB.getJdbcUrl(),
"spring.datasource.local.username=" + localMariaDB.getUsername(),
"spring.datasource.local.password=" + localMariaDB.getPassword(),
"spring.datasource.local.driver-class-name=" + localMariaDB.getDriverClassName(),
"spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect",

"spring.datasource.global.url=" + globalMariaDB.getJdbcUrl(),
"spring.datasource.global.username=" + globalMariaDB.getUsername(),
"spring.datasource.global.password=" + globalMariaDB.getPassword(),
"spring.datasource.global.driver-class-name=" + globalMariaDB.getDriverClassName(),
"spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDBDialect",

"keycloak.server-url=http://localhost:" + keycloak.getFirstMappedPort(),
"spring.security.oauth2.resourceserver.jwt.issuer-uri=http://localhost:" + keycloak.getFirstMappedPort() + "/realms/app",

"spring.kafka.bootstrap-servers="  + kafka.getBootstrapServers()
).applyTo(applicationContext.getEnvironment());
}
}
Я использую это в своем классе IntegrationTestBase следующим образом:

Код: Выделить всё

@ContextConfiguration(initializers = TestContainersInitializer.class)
Я не знаю, что еще нужно, чтобы этот подход работал (использовать существующую конфигурацию с данными контейнера).
Я также попробовал написать отдельную тестовую конфигурацию для баз данных:

Код: Выделить всё

@TestConfiguration
public class TestDatabaseConfiguration {

@Primary
@Bean
public DataSource localDataSource(Environment env) {
return DataSourceBuilder.create()
.url(env.getProperty("spring.datasource.local.url"))
.username(env.getProperty("spring.datasource.local.username"))
.password(env.getProperty("spring.datasource.local.password"))
.driverClassName(env.getProperty("spring.datasource.local.driver-class-name"))
.build();
}

@Bean
@Qualifier("globalDataSource")
public DataSource globalDataSource(Environment env) {
return DataSourceBuilder.create()
.url(env.getProperty("spring.datasource.global.url"))
.username(env.getProperty("spring.datasource.global.username"))
.password(env.getProperty("spring.datasource.global.password"))
.driverClassName(env.getProperty("spring.datasource.global.driver-class-name"))
.build();
}

@Primary
@Bean
public LocalContainerEntityManagerFactoryBean localEntityManagerFactory(
EntityManagerFactoryBuilder builder,
DataSource localDataSource) {
Map properties = new HashMap();
properties.put("hibernate.hbm2ddl.auto", "validate");
properties.put("hibernate.dialect", "org.hibernate.dialect.MariaDBDialect");

return builder
.dataSource(localDataSource)
.packages("com.utitech.bidhubbackend.local", "com.utitech.bidhubbackend.common.fileupload")
.properties(properties)
.build();
}

@Bean
public LocalContainerEntityManagerFactoryBean globalEntityManagerFactory(
EntityManagerFactoryBuilder builder,
@Qualifier("globalDataSource") DataSource globalDataSource) {
Map properties = new HashMap();
properties.put("hibernate.hbm2ddl.auto", "validate");
properties.put("hibernate.dialect", "org.hibernate.dialect.MariaDBDialect");

return builder
.dataSource(globalDataSource)
.packages("com.utitech.bidhubbackend.global", "com.utitech.bidhubbackend.common.fileupload")
.properties(properties)
.build();
}

@Primary
@Bean
public PlatformTransactionManager localTransactionManager(
@Qualifier("localEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}

@Bean
public PlatformTransactionManager globalTransactionManager(
@Qualifier("globalEntityManagerFactory") EntityManagerFactory entityManagerFactory) {
return new JpaTransactionManager(entityManagerFactory);
}
}
Для этого подхода в IntegrationTestBase я использовал свойство properties = {"spring.main.allow-bean-definition-overriding=true"}, что должно позволять переопределять bean-компоненты с похожими именами. Однако, что бы я ни пытался, я продолжаю сталкиваться с проблемой «ожидания базы данных».
Какие шаги мне следует предпринять, чтобы решить эту проблему и успешно протестировать приложение с несколькими контейнерами MariaDB? Следует ли мне изменить существующую конфигурацию или существует более подходящий подход для обработки подключения к базе данных для тестирования?

Подробнее здесь: https://stackoverflow.com/questions/790 ... containers
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «JAVA»