简体   繁体   English

无法使用第二个数据源运行Spring JUnit测试

[英]Not able to run Spring JUnit tests with second data source

I am using SpringJUnit4ClassRunner to run my integration tests. 我正在使用SpringJUnit4ClassRunner来运行集成测试。 I had to use two data sources in my Spring Boot REST web service because I want to use different database users for Liquibase and Application queries. 我必须在Spring Boot REST Web服务中使用两个数据源,因为我想对Liquibase和Application查询使用不同的数据库用户。 When I run the test, the second datasource is not getting created. 当我运行测试时,没有创建第二个数据源。

Following is my test code 以下是我的测试代码

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

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

Following is my datasource instantiation 以下是我的数据源实例化

@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;
    }
}

Following is the error message. 以下是错误消息。

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

When I use single data source, everything is working is as expected. 当我使用单个数据源时,一切正常。

I am working on a similar project, where I have two datasources. 我正在一个类似的项目中,我有两个数据源。 Here is what I do, datasource.primary.url=jdbc:mysql://localhost:3306/databaseName datasource.primary.username=username datasource.primary.password=password 这是我的工作, datasource.primary.url=jdbc:mysql://localhost:3306/databaseName datasource.primary.username=username datasource.primary.password=password

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

And in config class do just, 在config类中,

@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();
}

Wherever I need a datasource, I just autowire it like: 无论何时需要数据源,我都可以像这样自动布线:

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

Note: The datasource annotated @Primary will be injected if @Qualifier is not used while autowiring. 注意:如果在自动装配时未使用@Qualifier则将注入带注释的@Primary数据源。

Testing is much simpler with this. 这样测试就简单得多。 If you want to use in memory database for testing (most common technique), just provide another set of properties, with url of the in memory database, which can be used by the test class 如果要使用内存数据库进行测试(最常用的技术),只需提供另一组属性,以及内存数据库的URL,测试类就可以使用该属性

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM