[英]Test Config Beans Loaded into Spring Context During App Run
我正在开发一个 spring 启动(v 2.2.4)应用程序,专门添加集成测试,利用Testcontainers实例化一个 docker 容器,该容器运行 Postgres 实例以进行测试以执行数据库事务。 测试通过Liquibase将我们的数据库模式推送到 Postgres 实例中。 我按照本指南实施了这一点。 与测试时间 Postgres 的连接由名为 TestPostgresConfig.java 的 class 管理(见下文)。 liquibase 操作由同一个 class 中定义的 SpringLiquibase object 执行。 成功构建后尝试运行应用程序时遇到问题。 问题是 Spring 上下文尝试在运行时实例化 SpringLiquibase bean(由于 db.changelog-master.yaml 未找到而失败),我不希望它这样做:
WARN [main] org.springframework.context.support.AbstractApplicationContext:在上下文初始化期间遇到异常 - 取消刷新尝试:org.springframework.beans.factory.BeanCreationException:
在 class 路径资源中定义名称为“liquibase”的 bean 创建错误
[org/springframework/boot/autoconfigure/liquibase/LiquibaseAutoConfiguration$LiquibaseConfiguration.class]:init方法调用失败; 嵌套异常是 liquibase.exception.ChangeLogParseException: Error parsing classpath:db/changelog/changelog-master.yaml
Cause by java.io.FileNotFoundException class path resource [db/changelog/changelog-master.yaml] cannot be resolved to URL because it does not exist
这个文件不存在,永远不会存在于这个项目中,并且 liquibase 不应该首先尝试在运行时推送更改日志。 我需要帮助弄清楚为什么 Spring 会尝试加载 liquibase bean,以便我可以防止在运行时发生这种情况。
我的设置:
@SpringBootApplication
@EnableRetry
@EnableCommonModule
@EnableScheduling
@Slf4j
@EnableConfigurationProperties({
ExternalProperties.class,
ApplicationProperties.class
})
public class MyApplication implements WebMvcConfigurer, CommandLineRunner {
@Autowired
MyService myService;
public static void main(String[] args) {
SpringApplication.run(MyApplication.class, args);
}
public void run(String... args) throws Exception {
myService.doSomething();
}
}
TestPostgresConfig.java:
@TestConfiguration
@Profile("integration")
public class TestPostgresConfig {
@Bean
public DataSource dataSource() {
DriverManagerDataSource ds = new DriverManagerDataSource();
ds.setDriverClassName("org.postgresql.Driver");
ds.setUrl(format("jdbc:postgresql://%s:%s/%s", MyIT.psqlContainer.getContainerIpAddress(),
MyIT.psqlContainer.getMappedPort(5432), MyIT.psqlContainer.getDatabaseName()));
ds.setUsername(MyIT.psqlContainer.getUsername());
ds.setPassword(MyIT.psqlContainer.getPassword());
ds.setSchema(MyIT.psqlContainer.getDatabaseName());
return ds;
}
@Bean
public SpringLiquibase springLiquibase(DataSource dataSource) throws SQLException {
tryToCreateSchema(dataSource);
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setDropFirst(true);
liquibase.setDataSource(dataSource);
liquibase.setDefaultSchema("the_schema");
// This and all supported liquibase changelog files are copied onto my classpath
// via the maven assembly plugin. The config to do this has been omitted for the
// sake of brevity
// see this URL for how I did it:
// https://blog.sonatype.com/2008/04/how-to-share-resources-across-projects-in-maven/
liquibase.setChangeLog("classpath:/test/location/of/liquibase.changelog-root.yml");
return liquibase;
}
private void tryToCreateSchema(DataSource dataSource) throws SQLException {
String CREATE_SCHEMA_QUERY = "CREATE SCHEMA IF NOT EXISTS test";
dataSource.getConnection().createStatement().execute(CREATE_SCHEMA_QUERY);
}
}
MyIT.java:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes=CommonConfig.class)
@ActiveProfile("integration")
@Import(TestPostgresConfig.class)
public class MyIT {
@ClassRule
public static PostgreSQLContainer psqlContainer = new PostgreSQLContainer("postgres:13.1")
.withDatabseName("test-database-instance")
.withUsername("divdiff")
.withPassword("theseAreNotTheDroidsForYou123");
@BeforeClass
public static void init() {
System.setProperty("spring.datasource.url", "jdbc:postgresql://"
+ psqlContainer.getHost() + ":"
+ psqlContainer.getMappedPort(5432) + "/"
+ psqlContainer.getDatabaseName()));
System.setProperty("spring.datasource.username", psqlContainer.getUsername());
System.setProperty("spring.datasource.password", psqlContainer.getPassword());
}
@Before
public void setUp() {
// code to set up my test
}
@Test
public void testMyCodeEndToEnd() {
// my test implementation
}
}
MyConfig.java:
@Configuration
@ComponentScan(basePackages = "my.code")
@EntityScan("my.code")
@Slf4j
public class MyConfig {
@Bean
public KeyStore keyStore() {
//load keystore and set javax.net.ssl.keystore* properties
}
@Bean
public KeyStore trustStore() {
//load truststore and set javax.net.ssl.truststore* properties
}
@Bean
public RestTemplate restTemplate() {
//Set up and load SSL Context with key and trust store
//Create HTTPClient and connection stuff
//Look at this link for a similar set up
//https://www.baeldung.com/rest-template
}
}
应用程序集成.yml
spring:
jpa:
properties:
hibernate:
enable_lazy_load_no_trans: true
profiles:
active: default
server:
ssl:
# My key and trust store values
application:
unrelated-app-properties:
# propertie values below
Package结构:
应用程序项目/src/main/java/com/my/code/MyApplication.java
应用程序项目/src/main/java/com/my/code/service/MyService.java
app-project/src/test/java/my/code/OTHER-TEST-CLASSES-LIVE-HERE...
应用程序项目/src/test/java/integration/MyIT.java
应用程序项目/src/test/java/integration/TestPostgresConfig.java
app-project/src/test/resources/application-integration.yml
my-common-project/src/main/java/common/config/MyConfig.java
非常感谢您的帮助:!! :D
我是个白痴。 我为测试引入的 maven 依赖项是使用提供的 scope 而不是测试:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>project-with-db-changelogs</artifactId>
<version>1.0-SNAPSHOT</version>
<classifier>resources</classifier>
<type>zip</type>
<scope>provided</scope>
</dependency>
什么时候应该测试 scope:
<dependency>
<groupId>${project.groupId}</groupId>
<artifactId>project-with-db-changelogs</artifactId>
<version>1.0-SNAPSHOT</version>
<classifier>resources</classifier>
<type>zip</type>
<scope>test</scope>
</dependency>
根据 此链接,“这仅在 compile-classpath 和 test-classpath 中可用”,因此 liquibase 代码正在我的测试和生成的 jar 中运行。 #业余时间
您可以将 liqubase 上下文污染为测试
<changeSet author="name" id="id-of-file" context="test">
并具有如下应用程序属性:spring.liquibase.contexts=test
并添加一个 liquibase bean,如:
@Value("${spring.liquibase.contexts}") 私有字符串 liquibaseContexts;
@Bean
public SpringLiquibase liquibase() {
SpringLiquibase liquibase = new SpringLiquibase();
liquibase.setDataSource(localDatabaseDataSource);
liquibase.setShouldRun(liquibaseEnabled);
liquibase.setChangeLog(localDatabaseLiquibaseChangeLog);
liquibase.setContexts(liquibaseContexts);
return liquibase;
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.