RepositoryConfiguration

RepositoryConfiguration

我有一个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 要注意RepositoryConfigurationAuditControllerTest在同一包装中?

更新:这是当前配置:( 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 会有很多奇怪的构建错误和解决问题。 (以及以后必须继承您的代码的每个开发人员)...

欢迎评论/问题。

08-17 16:59