Spring Boot 如何使用HikariConfig实现数据源配置的单元测试

vlf7wbxs  于 2023-01-05  发布在  Spring
关注(0)|答案(1)|浏览(238)

这是我的DatasourceConfiguration.java文件,它是一个配置文件,用于设置光配置,QuartzDatasource是基于光配置构建的。

import com.zaxxer.hikari.HikariConfig;
import com.zaxxer.hikari.HikariDataSource;
import javax.sql.DataSource;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.quartz.QuartzDataSource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class DatasourceConfiguration {
  @Value("${spring.datasource.scheduler.jdbcUrl}")
  private String jdbcUrl;

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

  @Value("${spring.datasource.scheduler.driverClassname}")
  private String driverClassname;

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

  @Bean
  public HikariConfig hikariConfig() {
    HikariConfig hikariConfig = new HikariConfig();
    hikariConfig.setDriverClassName(driverClassname);
    hikariConfig.setJdbcUrl(jdbcUrl);
    hikariConfig.setUsername(userName);
    hikariConfig.setPassword(password);
    return hikariConfig;
  }

  @Bean(name = "quartzDataSource")
  @QuartzDataSource
  public DataSource dataSource() {
    return new HikariDataSource(hikariConfig());
  }
}

下面是我的DatasourceConfigurationTest.java文件:

import com.zaxxer.hikari.HikariDataSource;
import org.springframework.context.ApplicationContext;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.jupiter.SpringExtension;

import javax.sql.DataSource;
import java.sql.SQLException;

import static org.assertj.core.api.Assertions.assertThat;

@ExtendWith(SpringExtension.class)
@TestPropertySource(locations = "classpath:application.properties")
@ContextConfiguration(classes = DatasourceConfiguration.class)
class DatasourceConfigurationTest {

  @Autowired
  private ApplicationContext context;

  @Test
  void validateConfiguration() throws SQLException {
    assertThat(this.context.getBeansOfType(DataSource.class)).hasSize(1);
    HikariDataSource dataSource = this.context.getBean(HikariDataSource.class);
    assertThat(dataSource.getConnection().getMetaData().getURL()).isEqualTo("jdbc:h2:mem:simple");
    assertThat(dataSource.getMaximumPoolSize()).isEqualTo(42);
  }
}

运行单元测试时,我发现它未能加载ApplicationContext。以下是日志:

java.lang.IllegalStateException: Failed to load ApplicationContext
              at org.springframework.test.context.cache.DefaultCacheAwareContextLoaderDelegate.loadContext(DefaultCacheAwareContextLoaderDelegate.java:132)
              at org.springframework.test.context.support.DefaultTestContext.getApplicationContext(DefaultTestContext.java:124)
              at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:118)
              at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.prepareTestInstance(DependencyInjectionTestExecutionListener.java:83)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'getHikariConfig' defined in com.gm.gcc.vas.utility.messageretry.config.DatasourceConfiguration: Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariConfig]: Factory method 'getHikariConfig' threw exception; nested exception is java.lang.RuntimeException: Failed to load driver class test-driver-classname in either of HikariConfig class loader or Thread context classloader
              at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:658)
              at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:486)
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [com.zaxxer.hikari.HikariConfig]: Factory method 'getHikariConfig' threw exception; nested exception is java.lang.RuntimeException: Failed to load driver class test-driver-classname in either of HikariConfig class loader or Thread context classloader
              at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:185)
              at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:653)
              ... 87 common frames omitted
Caused by: java.lang.RuntimeException: Failed to load driver class test-driver-classname in either of HikariConfig class loader or Thread context classloader
              at com.zaxxer.hikari.HikariConfig.setDriverClassName(HikariConfig.java:491)
              at com.gm.gcc.vas.utility.messageretry.config.DatasourceConfiguration.getHikariConfig(DatasourceConfiguration.java:37)
              ... 88 common frames omitted

下面是属性文件:

spring.datasource.scheduler.driverClassname=test-driver-classname
spring.datasource.scheduler.jdbcUrl=jdbc:test-url
spring.datasource.scheduler.password=test-password
spring.datasource.scheduler.username=test-username

据我所知,当尝试创建一个连接时,由于伪值而失败。我只是想知道我做单元测试的方法是否正确,如果正确,我如何修复ApplicationContext错误?另外,确保100%收敛的正确方法是什么?

jc3wubiy

jc3wubiy1#

如果你想执行集成测试,你需要一个Spring可以连接到的正在运行的DB示例,你的测试不是一个单元测试,因为它是用SpringExtension扩展的。
您可以使用嵌入式H2数据库进行测试,然后需要将H2作为测试依赖项添加到pom.xml中:

<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <scope>test</scope>
</dependency>

application-test.properties中:

spring.datasource.scheduler.driverClassname=org.h2.Driver
spring.datasource.scheduler.jdbcUrl=jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
spring.datasource.scheduler.password=sa
spring.datasource.scheduler.username=sa

要为测试加载application-test.properties,您应该将@TestPropertySource(locations = "classpath:application.properties")替换为@ActiveProfiles("test")或引用文件@TestPropertySource(locations = "classpath:application-test.properties")
另一个不错的选择是使用Testcontainers项目,它允许您在docker容器中运行生产中使用的数据库(如Postgres或MySQL)。

相关问题