我有一个SpringBootTest
测试,应该依赖一个单独的类来设置嵌入式Postgres和数据源。
因此,存储库配置如下所示:
package com.stream.repository.configuration
@Configuration
@ComponentScan(basePackages = arrayOf("com.stream.repository"))
@EntityScan(basePackages = arrayOf("com.stream.repository"))
@EnableJpaRepositories(basePackages = arrayOf("com.stream.repository"))
@EnableAutoConfiguration
class RepositoryConfiguration {
测试类如下所示:
package com.stream.webapp.rest
@AutoConfigureMockMvc(addFilters = false)
@SpringBootTest(properties =
[
"spring.jpa.hibernate.ddl-auto=validate",
"spring.jpa.show-sql=true",
"spring.liquibase.enabled=true",
"spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.yml",
"spring.jpa.properties.hibernate.jdbc.time_zone=UTC"
],
classes = [RepositoryConfiguration::class, AuditController::class],
webEnvironment = SpringBootTest.WebEnvironment.MOCK)
class AuditControllerTest {
这就是奇怪的地方。如果使用该配置运行,它将抱怨找不到
EntityManagerFactory
经过很多混乱之后,我找到了解决此问题的方法。
如果我移动
RepositoryConfiguration
使其位于com.stream.webapp.rest
包中,即与AuditControllerTest
相同,则它可以神奇地工作。我似乎找不到的任何原因。有人可以解释吗,有没有解决的办法?因为我不想移动它。将其放置在原处很有意义。
附带说明一下,它是用Kotlin编写的,但我看不出在这种情况下为什么如此重要。
这仅用于测试。在测试范围之外运行应用程序时,它可以工作
我还可以添加
AuditControllerTest
在一个模块中,RepositoryConfiguration
在另一个模块中。如果将它放在“正确的”包中(仍然是单独的模块),则不确定它是否相关,因为它是否有效TL; DR 的问题:为什么 Spring 要注意
RepositoryConfiguration
与AuditControllerTest
在同一包装中?更新:这是当前配置:(
RepositoryConfiguration
不变@AutoConfigureMockMvc(addFilters = false)
@ComponentScan("com.stream.repository")
@Configuration
@SpringBootTest(properties =
[
"spring.jpa.hibernate.ddl-auto=validate",
"spring.jpa.show-sql=true",
"spring.liquibase.enabled=true",
"spring.liquibase.change-log=classpath:db/changelog/db.changelog-master.yml",
"spring.jpa.properties.hibernate.jdbc.time_zone=UTC",
"database.dbname=stream_mapper"
],
classes = [com.stream.repository.configuration.RepositoryConfiguration::class, ExceptionMapper::class, AuditController::class],
webEnvironment = SpringBootTest.WebEnvironment.MOCK)
class AuditControllerTest {
最佳答案
Spring对此感到很奇怪,并且期望测试和主项目的包层次结构相等或大致相等。这样做是最佳做法,以后会为您节省很多头痛。
为了配置您的Integration Test,在主Spring Boot Configuration的同一包层次结构中放入“BaseIntegrationTest.java”或“AbstractIntegrationTest.java”之类的内容,用“test”代替“main”。
例如:
主要配置在这里:
src/main/java/com/stream/repository/configuration/RepositoryConfiguration.java
测试配置将在此处(使用@SpringBootTest)
src/test/java/com/stream/repository/configuration/TestRepositoryConfiguration.java
在上面的结构中,您已将大多数(或全部)Spring Boot测试配置注释放在基本的测试配置类(TestRepositoryConfiguration.java)上
然后您的实际测试将扩展此类:
例如:
src/test/java/com/stream/webapp/rest/AuditControllerTest.java
将以:
class AuditControllerTest extends TestRepositoryConfiguration { ... }
此外,关于发布的主要RepositoryConfiguration.java类还有一些奇怪的事情-因为它具有通用的@EnableAutoConfiguration批注,在特定于存储库的配置上不需要该批注-它自动包含在的@SpringBootApplication批注中您的基本Web应用程序。
关于您的集成测试,
理想情况下,@ SpringBootTest最好不要放在此文件中,即使为了简化起见,大多数指南都在其示例类中添加了该注释。理想情况下,您需要将此文件放置在与定义@SpringBootApplication的主应用程序基本配置文件具有相同结构(除了test而不是main)的结构中的基本集成测试文件(通常是抽象文件),并保持层次结构继承与测试配置和主要配置类相似。
这是一篇有关优化集成测试的精彩文章-I.E.对于相同类型的所有测试,请保持该应用程序的一个实例运行。
https://www.baeldung.com/spring-tests
另外,如果只需要测试存储库,请考虑使用@JdbcTest。如果要从主集成测试中提取特定于回购协议(protocol)的测试,可以将其保留为单独的上下文/测试类型,而不是从主应用程序测试扩展而来。
显然,我无权访问您的整个代码库,因此很难提出要完全解决任何问题的任何建议,但是希望这可以使您沿着结构化设置集成测试的正确思路进行思考,以避免 future 会有很多奇怪的构建错误和解决问题。 (以及以后必须继承您的代码的每个开发人员)...
欢迎评论/问题。