【问题标题】:Not able to run Spring JUnit tests with second data source无法使用第二个数据源运行 Spring JUnit 测试
【发布时间】:2016-03-03 23:04:09
【问题描述】:

我正在使用 SpringJUnit4ClassRunner 来运行我的集成测试。我必须在我的 Spring Boot REST Web 服务中使用两个数据源,因为我想为 Liquibase 和 Application 查询使用不同的数据库用户。当我运行测试时,没有创建第二个数据源。

以下是我的测试代码

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
@IntegrationTest
public class DomainServiceImplTest {

    @Test
    public void testCreateDomain() throws Exception {
    }
}

以下是我的数据源实例化

@Configuration
@EnableTransactionManagement
public class DatabaseConfiguration {

    private final Logger log = LoggerFactory.getLogger(DatabaseConfiguration.class);

    @Inject
    private Environment env;

    @Autowired(required = false)
    private MetricRegistry metricRegistry;

    @Bean(destroyMethod = "close")
    @Primary
    public DataSource dataSource(DataSourceProperties dataSourceProperties, NileRegistrarProperties nileRegistrarProperties) {
        log.debug("Configuring Datasource");
        if (dataSourceProperties.getUrl() == null) {
            log.error("Your database connection pool configuration is incorrect! The application" +
                    " cannot start. Please check your Spring profile, current profiles are: {}",
                Arrays.toString(env.getActiveProfiles()));

            throw new ApplicationContextException("Database connection pool is not configured correctly");
        }
        HikariConfig config = new HikariConfig();
        config.setDriverClassName(dataSourceProperties.getDriverClassName());
        config.setJdbcUrl(dataSourceProperties.getUrl());
        if (dataSourceProperties.getUsername() != null) {
            config.addDataSourceProperty("user", dataSourceProperties.getUsername());
        } else {
            config.addDataSourceProperty("user", ""); // HikariCP doesn't allow null user
        }
        if (dataSourceProperties.getPassword() != null) {
            config.addDataSourceProperty("password", dataSourceProperties.getPassword());
        } else {
            config.addDataSourceProperty("password", ""); // HikariCP doesn't allow null password
        }

        //MySQL optimizations, see https://github.com/brettwooldridge/HikariCP/wiki/MySQL-Configuration
        if ("com.mysql.jdbc.jdbc2.optional.MysqlDataSource".equals(dataSourceProperties.getDriverClassName())) {
            config.addDataSourceProperty("cachePrepStmts", nileRegistrarProperties.getDatasource().isCachePrepStmts());
            config.addDataSourceProperty("prepStmtCacheSize", nileRegistrarProperties.getDatasource().getPrepStmtCacheSize());
            config.addDataSourceProperty("prepStmtCacheSqlLimit", nileRegistrarProperties.getDatasource().getPrepStmtCacheSqlLimit());
        }
        if (metricRegistry != null) {
            config.setMetricRegistry(metricRegistry);
        }
        return new HikariDataSource(config);
    }

    @Bean(destroyMethod = "close")
    public DataSource liquibaseDataSource(DataSourceProperties dataSourceProperties, LiquibaseProperties liquibaseProperties) {
        log.debug("Configuring Liquibase Datasource");
        if (dataSourceProperties.getUrl() == null) {
            log.error("Your database connection pool configuration is incorrect! The application" +
                    " cannot start. Please check your Spring profile, current profiles are: {}",
                Arrays.toString(env.getActiveProfiles()));

            throw new ApplicationContextException("Database connection pool is not configured correctly");
        }
        HikariConfig config = new HikariConfig();
        config.setDriverClassName(dataSourceProperties.getDriverClassName());
        config.setJdbcUrl(dataSourceProperties.getUrl());
        // Close all connections after liquibase operation is complete.
        config.setMinimumIdle(0);
        if (dataSourceProperties.getUsername() != null) {
            config.addDataSourceProperty("user", liquibaseProperties.getUser());
        } else {
            config.addDataSourceProperty("user", ""); // HikariCP doesn't allow null user
        }
        if (dataSourceProperties.getPassword() != null) {
            config.addDataSourceProperty("password", liquibaseProperties.getPassword());
        } else {
            config.addDataSourceProperty("password", ""); // HikariCP doesn't allow null password
        }

        return new HikariDataSource(config);
    }

    @Bean
    public SpringLiquibase liquibase(@Qualifier("liquibaseDataSource") DataSource dataSource,
                                     LiquibaseProperties liquibaseProperties) {

        // Use liquibase.integration.spring.SpringLiquibase if you don't want Liquibase to start asynchronously
        SpringLiquibase liquibase = new AsyncSpringLiquibase();
        liquibase.setDataSource(dataSource);
        liquibase.setChangeLog("classpath:config/liquibase/master.xml");
        liquibase.setContexts(liquibaseProperties.getContexts());
        liquibase.setDefaultSchema(liquibaseProperties.getDefaultSchema());
        liquibase.setDropFirst(liquibaseProperties.isDropFirst());
        liquibase.setShouldRun(liquibaseProperties.isEnabled());

        log.debug("Configuring Liquibase");

        return liquibase;
    }
}

以下是错误信息。

Error creating bean with name 'dataSourceInitializer': Invocation of init method failed;

当我使用单一数据源时,一切正常。

【问题讨论】:

  • 我刚刚意识到数据源在测试期间变成了 h2 DB,并且我的 LiquibaseProperties 文件没有初始化。
  • 为什么不使用 application.properties 进行数据源配置?
  • @RahulSharma 我仅将 application.yml 用于配置。您是在谈论在测试用例中使用吗?

标签: java spring junit spring-boot spring-bean


【解决方案1】:

我正在做一个类似的项目,我有两个数据源。这就是我所做的, datasource.primary.url=jdbc:mysql://localhost:3306/databaseName datasource.primary.username=username datasource.primary.password=password

同样对于第二个数据源, datasource.secondary.url=jdbc:mysql://localhost:3306/databaseName datasource.secondary.username=username datasource.secondary.password=password

而在配置类中就这样做,

@Bean
@Primary
@ConfigurationProperties(prefix = "datasource.primary")
public DataSource primaryDataSource() {
    return DataSourceBuilder.create().build();
}

@Bean(name = "secondaryDatasource")
@ConfigurationProperties(prefix = "datasource.secondary")
public DataSource secondaryDataSource() {
    return DataSourceBuilder.create().build();
}

无论我在哪里需要数据源,我都可以像这样自动装配它:

public void setJdbcTemplate(@Qualifier("secondaryDatasource") DataSource dataSource) {
    this.jdbcTemplate = new NamedParameterJdbcTemplate(dataSource);
}

注意:如果在自动装配时不使用@Qualifier,则注解@Primary 的数据源将被注入。

有了这个,测试就简单多了。如果你想使用内存数据库进行测试(最常用的技术),只需提供另一组属性,内存数据库的url,测试类可以使用它

【讨论】:

  • 我已经这样做了。但这将保持连接池打开,即使我只在应用程序启动期间需要 liquibase 连接.. ?
  • 这有关系吗?您正在使用它进行测试。一旦测试完成,它将自动关闭。
猜你喜欢
  • 1970-01-01
  • 2021-09-05
  • 2015-11-06
  • 1970-01-01
  • 2015-08-27
  • 1970-01-01
  • 2014-11-29
  • 2018-11-17
  • 2017-09-08
相关资源
最近更新 更多