当前位置: 首页 > 知识库问答 >
问题:

使用spring boot liquibase对多个数据源不起作用的测试

顾跃
2023-03-14

我正在为具有多个数据源的spring boot应用程序创建unittesting。(配置很大程度上受到了这个答案的启发)

@Configuration
public class DatasourceConfig {

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

    @Bean
    @ConfigurationProperties(prefix = "datasource.primary.liquibase")
    public LiquibaseProperties primaryLiquibaseProperties() {
        return new LiquibaseProperties();
    }

    @Bean
    public SpringLiquibase primaryLiquibase() {
        return springLiquibase(primaryDataSource(), primaryLiquibaseProperties());
    }

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

    @Bean
    @ConfigurationProperties(prefix = "datasource.secondary.liquibase")
    public LiquibaseProperties secondaryLiquibaseProperties() {
        return new LiquibaseProperties();
    }

    @Bean
    public SpringLiquibase secondaryLiquibase() {
        return springLiquibase(secondaryDataSource(), secondaryLiquibaseProperties());
    }

    private static SpringLiquibase springLiquibase(DataSource dataSource, LiquibaseProperties properties) {
        SpringLiquibase liquibase = new SpringLiquibase();
        liquibase.setDataSource(dataSource);
        liquibase.setChangeLog(properties.getChangeLog());
        liquibase.setContexts(properties.getContexts());
        liquibase.setDefaultSchema(properties.getDefaultSchema());
        liquibase.setDropFirst(properties.isDropFirst());
        liquibase.setShouldRun(properties.isEnabled());
        liquibase.setLabels(properties.getLabels());
        liquibase.setChangeLogParameters(properties.getParameters());
        liquibase.setRollbackFile(properties.getRollbackFile());
        return liquibase;
    }


...

}

而且

datasource:
  primary:
    url: jdbc:mysql://localhost/primary
    username: username
    password: password
    liquibase:
      change-log: classpath:/db/changelog/db.primary.changelog-master.xml
  secondary:
    url: jdbc:mysql://localhost/secondary
    username: username
    password: password
    liquibase:
      change-log: classpath:/db/changelog/db.secondary.changelog-master.xml

应用程序运行正常。

management:
  endpoints.web.exposure.include: "*"
  security.enabled: false
spring:
  zipkin:
    discoveryClientEnabled: false
    sender:
      type: kafka
      #type: web
  liquibase:
    enabled: false
  datasource:
    url: "jdbc:h2:mem:testdb"
    jdbc-url: "jdbc:h2:mem:testdb"
    username: sa
    password:
  secondary-datasource:
    url: "jdbc:h2:mem:testdb"
    jdbc-url: "jdbc:h2:mem:testdb"
    username: sa
    password:
datasource:
 primary-liquibase:
   liquibase:
     url: "jdbc:h2:mem:testdb"
     username: sa
     password:
 secondary-liquibase:
   liquibase:
     url: "jdbc:h2:mem:testdb"
     username: sa
     password:
liquibase:
  enable: false
package com.foo.bar.car;

import com.foo.bar.car.utils.KSUIDGenerator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.springframework.boot.jdbc.EmbeddedDatabaseConnection;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.autoconfigure.web.servlet.AutoConfigureMockMvc;
import org.springframework.boot.test.context.SpringBootTest;

@SpringBootTest
@AutoConfigureMockMvc
@AutoConfigureTestDatabase
// https://stackoverflow.com/a/58786742/1534925
//@AutoConfigureTestDatabase(replace = AutoConfigureTestDatabase.Replace.NONE)
//@AutoConfigureTestDatabase(connection = EmbeddedDatabaseConnection.H2)
class CarApplicationTests {

    @Test
    public void contextLoads() {
        String h = "Hello World!";
        Assertions.assertEquals(h, "Hello World!");
    }

    @Test
    public void testKSUIDGeneration() {
        Assertions.assertNotNull(KSUIDGenerator.generateKSUID());
    }
}
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [liquibase.integration.spring.SpringLiquibase]: Factory method 'primaryLiquibase' threw exception; nested exception is java.lang.IllegalArgumentException: No visible constructors in class org.springframework.boot.test.autoconfigure.jdbc.TestDatabaseAutoConfiguration$EmbeddedDataSourceFactoryBean

不确定缺少了什么配置更改。

共有1个答案

司马高明
2023-03-14

要使其发挥作用,需要做几项调整:

>

  • 在CarApplication.java中排除DB和Liquibase的自动配置

    @SpringBootApplication(exclude={DataSourceAutoConfiguration.Class,LiquiBaseAutoConfiguration.Class})

    仔细检查下面的设置,以防在上面列出的所有调整后它都不起作用(我改变了这里和那里的东西,我通常的编码方式使它对我来说舒服):

    CarApplication.java

    @SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, 
                                       LiquibaseAutoConfiguration.class })
    public class CarApplication {
      public static void main(String[] args) {
        SpringApplication.run(CarApplication.class, args);
      }
    }
    

    application.yaml

    server:
      port: 9999
    
    datasource:
      url: jdbc:postgresql://localhost:8888/foo
      jdbcUrl: jdbc:postgresql://localhost:5432/foo
      username: username
      password: password
      driverClassName: org.postgresql.Driver
      liquibase:
        change-log: classpath:db-changelog/primary.xml
    
    secondary-datasource:
      url: jdbc:postgresql://localhost:8888/bar
      jdbcUrl: jdbc:postgresql://localhost:5432/bar
      username: username
      password: password
      driverClassName: org.postgresql.Driver
      liquibase:
        change-log: classpath:db-changelog/secondary.xml
    
    @Configuration
    public class DatabaseConfig {
    
        @Bean
        @Primary
        @ConfigurationProperties(prefix = "datasource")
        public DataSource primaryDataSource() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean
        @ConfigurationProperties(prefix = "secondary-datasource")
        public DataSource secondaryDataSource() {
            return DataSourceBuilder.create().build();
        }
    
        @Bean
        @ConfigurationProperties(prefix = "datasource.liquibase")
        public LiquibaseProperties primaryLiquibaseProperties() {
            return new LiquibaseProperties();
        }
    
        @Bean("liquibase")
        public SpringLiquibase primaryLiquibase() {
            return springLiquibase(primaryDataSource(), primaryLiquibaseProperties());
        }
    
        @Bean
        @ConfigurationProperties(prefix = "secondary-datasource.liquibase")
        public LiquibaseProperties secondaryLiquibaseProperties() {
            return new LiquibaseProperties();
        }
    
        @Bean
        public SpringLiquibase secondaryLiquibase() {
            return springLiquibase(secondaryDataSource(), secondaryLiquibaseProperties());
        }
    
        private static SpringLiquibase springLiquibase(DataSource dataSource, LiquibaseProperties properties) {
            SpringLiquibase liquibase = new SpringLiquibase();
            liquibase.setDataSource(dataSource);
            liquibase.setChangeLog(properties.getChangeLog());
            liquibase.setContexts(properties.getContexts());
            liquibase.setDefaultSchema(properties.getDefaultSchema());
            liquibase.setDropFirst(properties.isDropFirst());
            liquibase.setShouldRun(properties.isEnabled());
            liquibase.setLabels(properties.getLabels());
            liquibase.setChangeLogParameters(properties.getParameters());
            liquibase.setRollbackFile(properties.getRollbackFile());
            return liquibase;
        }
    }
    
    datasource:
      url: "jdbc:h2:mem:testdb"
      jdbc-url: "jdbc:h2:mem:testdb"
      username: sa
      password:
      liquibase:
        change-log: classpath:db-changelog/primary.xml
    
    secondary-datasource:
      url: "jdbc:h2:mem:testdb"
      jdbc-url: "jdbc:h2:mem:testdb"
      username: sa
      password:
      liquibase:
        change-log: classpath:db-changelog/secondary.xml
    
    @SpringBootTest
    class CarApplicationTests {
        @Test
        public void contextLoads() {
            String h = "Hello World!";
            Assertions.assertEquals(h, "Hello World!");
        }
        @Test
        public void testKSUIDGeneration() {
            Assertions.assertNotNull(KSUIDGenerator.generateKSUID());
        }
    }
    

  •  类似资料:
    • 当我试图在spring-boot上使用多个数据源时,我面临着一个巨大的问题。我的问题是因为我正在使用spring batch,而我没有足够的权限在我的生产数据库上从spring-batch创建元数据表,所以我需要使用例如H2来创建这些表,但是当我试图在我的模型中加载一个在我的作业处理器中具有关系为@OneToMany的字段时,我收到了LazyInitializationException Spri

    • 我试着用Twilio发一条短信,如下所示: 我得到以下错误:

    • 我试图创建一个Spring Boot应用程序,它连接两个数据源。我可以通过遵循Spring文档来实现这一点,但我面临的挑战是实现以下目标 null 是否有任何方法可以使用Spring Boot的自动配置功能来实现这一点,或者我必须基于概要文件创建不同的数据源bean。

    • 我有一个简单的SpringBoot应用程序,我想使用AutoConfiguration来配置Tomcat jdbc池数据源。 我正在使用这些Spring依赖项: 以下是我的 application.yml 文件中的数据源属性: 我确定正在加载属性,因为应用程序正在获取其他值。 我在配置文件中将 bean 定义为: 我将数据源注入到我的DAO中,如下所示: 如果我在getDataSource()方法

    • 我正试图使用INFOQ提供的本教程设置一个包含多个数据源的Springboot(v2.0.0.BUILD-SNAPSHOT)项目 https://www.infoq.com/articles/Multiple-Databases-with-Spring-Boot 但是我需要使用多个EntityManager来代替JdbcTemplate 这是我目前掌握的情况 应用属性 一个pplication.j