问题描述
我正在为具有多个数据源的Spring Boot应用程序创建单元测试. (配置受到此答案的启发)
I am creating unittesting for spring boot application having multiple datasources. (Configuration is heavily inspired from this answer)
@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
应用程序正常运行.
问题是此配置的单元测试失败.我已经使用h2
作为嵌入式数据库.添加了h2作为测试依赖项,并在数据源URL中以及在application.yaml中添加了h2进行测试.
The problem is unit testing is failing with this configuration. I have used h2
as embedded DB. Added h2 as test dependency and added h2 in datasource URL as well in application.yaml for testing.
application.yaml用于测试
application.yaml for testing
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());
}
}
我创建了一个存储库进行演示.
I have created a repository to demonstrate this.
当我执行gradlew clean check
时,会出现以下错误
When I do gradlew clean check
it gives me following error
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
不确定我缺少什么配置更改.
Not sure what configuration change I am missing.
推荐答案
要使其正常运行,需要进行一些调整:
There are several adjustments to be done to make it work:
-
在CarApplication.java中排除DB和Liquibase的自动配置
Exclude Autoconfiguration for DB and Liquibase in your CarApplication.java
@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class, LiquibaseAutoConfiguration.class})
@SpringBootApplication(exclude = { DataSourceAutoConfiguration.class, LiquibaseAutoConfiguration.class })
摆脱配置中的sping
前缀(包括应用程序和测试属性)
Get rid of sping
prefix in your configuration (both in app and test properties)
添加liquibase更改日志位置以测试属性
Add liquibase changelog location to test properties
仔细检查下面的设置,以防在上面列出的所有调整之后仍然无法正常工作(我在这里和那里更改了内容,通常使用使我感到舒服的方式进行编码):
Double check with the setup below in case it wont work after all listed above adjustments (I changed things here and there the way I usually code to make it comfortable to me):
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
DatabaseConfig.java
@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;
}
}
测试application.yaml
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
CarApplicationTest.java
@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 Liquibase测试不适用于多个数据源的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!