为什么几乎相同的服务不需要@ComponentScan来访问库bean?

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

我们创建了一个新的 Spring Boot 服务。作为其中的一部分,我们希望通过更有效地利用测试切片(而不是在整个上下文中加载)来改善我们的一般测试习惯。我们正在效仿另一项服务的示例,该服务已经非常有效地利用了较小的测试切片。

然而,当我们尝试让存储库测试开始使用时,我们遇到了一个令人心烦意乱的问题

@DataJpaTest

对于上下文:有一些常见的内部库,其中包括需要自动装配的 Spring bean。解决这个问题的常见解决方案是使用

@ComponentScan
。对于常规集成测试,这工作得很好。然而,当尝试使用较小的测试切片(如
@DataJpaTest
)时,注释将尝试自动装配 all beans,其中一些在当前上下文中无法自动装配。

我们已经通过删除

@ComponentScan
解决了这个问题,但是我们没有可用的库 bean,并且应用程序以及完整的集成测试将无法启动。

现在这本身就很好并且相对预期。 但是回到前面提到的服务。 他们根本不使用

@ComponentScan
!!!出于某种原因,该服务只是像魔术一样自动装配外部库bean。我们已经研究了互联网提供的关于获取外部 bean 的几乎所有内容,而其他服务不使用那里的任何内容。

由于某种原因,外部 bean 只能用于其应用程序上下文。他们的

@DataJpaTest
类也不会尝试加载不必要的(且不可用的)bean。我们已经与其他团队交谈过,他们也不知道他们正在做任何特别的事情。当他们开始使用库时,一切都正常了。

那么,两个几乎相同的服务表现如此不同的原因可能是什么?问题不在于让所有测试正常工作(例如过滤掉测试类中的 bean)。我们想了解为什么一个服务可以访问 Bean,而另一个服务必须绕圈运行并跳过障碍。

我们已经尝试过:

  • 没有
    @ComponentScan
    (完整的应用程序上下文将无法启动)
  • 尝试其他配置方法获取bean(没有效果)
  • 模拟错误的bean(毫无意义的任务,因为有数十个甚至数百个)
  • 比较所有依赖项及其版本(无效)

需要指出的是,这两个服务的配置是基本相同

spring-boot junit component-scan
1个回答
0
投票

正如经常发生的那样,当我绝望并在这里写下一个问题时,一位队友注意到两个服务之间的包域不匹配。

我们最近刚刚经历了顶级域名变更。新域有一个字符不同。其他服务和库在包名称中使用旧域,新服务使用新域。

因此,对于工作服务,他们不需要

@ComponentScan
,因为
@ComponentScan
上的默认
@SpringBootApplication
也与库 bean 匹配。 默认的
@ComponentScan
有过滤器,似乎可以在测试期间过滤掉不必要的 bean。

因此,简单的修复方法是将默认过滤器也添加到新服务的

@ComponentScan

@ComponentScan(
    value = {"old.domain.package.library.*", "new.domain.package.*"},
    excludeFilters = {
        @Filter(
            type = FilterType.CUSTOM,
            classes = {TypeExcludeFilter.class}
        ),
        @Filter(
            type = FilterType.CUSTOM,
            classes = {AutoConfigurationExcludeFilter.class}
        )
    })
© www.soinside.com 2019 - 2024. All rights reserved.