使用 @ApplicationModuleTest 进行 Spring Modulith 集成测试中 Feign 客户端的问题

问题描述 投票:0回答:1

我正在使用 Spring Modulith 1.2.4 开发一个 Spring Boot 3.1 项目,有两个不同的模块:amadeus 和 collinson。每个模块都有自己的 Feign 客户端:

  • amadeus.client.AmadeusFeignClient
  • collinson.client.CollinsonFeignClient

应用程序在生产中完美运行,但在使用 @ApplicationModuleTest 为每个模块运行集成测试时遇到问题。例如:

  • 运行 AmadeusService 的集成测试时,我收到一条错误消息,指出 CollinsonFeignClient 不可用:
    No bean named 'com.demo.app.collinson.client.CollinsonFeignClient' available 
  • 运行 CollinsonService 的测试时,我在 AmadeusFeignClient:
    No bean named 'com.demo.app.amadeus.client.AmadeusFeignClient' available 
  • 中收到类似的错误

以下是我在测试中使用的注释:

@ApplicationModuleTest
class AmadeusServiceIT {
    // test implementation
}

@ApplicationModuleTest
class CollinsonServiceIT {
    // test implementation
}

但是,如果我从 @ApplicationModuleTest 切换到 @SpringBootTest,测试运行不会出现问题,这表明 Feign 客户端可能会忽略@ApplicationModuleTest 提供的模块隔离。

我的理解是@ApplicationModuleTest应该在测试期间隔离每个模块的bean,但Spring Cloud OpenFeign似乎不尊重这种隔离,导致需要跨模块bean。

有人在 Spring Modulith 上下文中遇到过 Feign 客户端的类似问题吗?

有没有办法配置 @ApplicationModuleTest 或 Feign 以在测试期间尊重模块隔离?

java spring-boot integration-testing spring-cloud-feign spring-modulith
1个回答
0
投票

经过一番调查,我找到了问题的根本原因。它将 @EnableFeignClients 放在主 com.demo.app.DemoApplication 类上

package com.demo.app
@SpringBootApplication
@EnableFeignClients
DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }

}

这导致无论我正在测试哪个模块,所有 Feign 客户端都会被加载。这导致不同模块的集成测试失败,因为他们试图从不相关的模块加载 Feign 客户端。

解决方案:

  • 从根应用程序类中删除@EnableFeignClients
  • 使用@EnableFeignClients在每个模块中创建一个配置类。我将 @EnableFeignClients 注释移至每个模块内的配置类。这可确保仅加载与该特定模块相关的 Feign 客户端。
package com.demo.app.collinson
@Configuration
@EnableFeignClients
public class CollinsonModuleConfig {
}
package com.demo.app.amadeus
@Configuration
@EnableFeignClients
public class AmadeusModuleConfig {
}

结果:

通过将 @EnableFeignClients 的范围限定到每个模块,我实现了模块之间的适当隔离,确保在测试期间加载正确的 Feign 客户端。这种方法解决了与无关模块中缺少 Feign 客户端 bean 相关的错误。

© www.soinside.com 2019 - 2024. All rights reserved.