无法 运行 Spring 使用第二个数据源进行 JUnit 测试
Not able to run Spring JUnit tests with second data source
我正在使用 SpringJUnit4ClassRunner 来 运行 我的集成测试。我不得不在 Spring Boot REST Web 服务中使用两个数据源,因为我想对 Liquibase 和应用程序查询使用不同的数据库用户。当我 运行 测试时,没有创建第二个数据源。
以下是我的测试代码
@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;
当我使用单一数据源时,一切正常。
我正在做一个类似的项目,我有两个数据源。这就是我所做的,
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
并且在配置中 class 只做,
@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,可供测试使用class[=16] =]
我正在使用 SpringJUnit4ClassRunner 来 运行 我的集成测试。我不得不在 Spring Boot REST Web 服务中使用两个数据源,因为我想对 Liquibase 和应用程序查询使用不同的数据库用户。当我 运行 测试时,没有创建第二个数据源。
以下是我的测试代码
@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;
当我使用单一数据源时,一切正常。
我正在做一个类似的项目,我有两个数据源。这就是我所做的,
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
并且在配置中 class 只做,
@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,可供测试使用class[=16] =]