【问题标题】:How to override Spring Bean in integration test with custom bean definition?如何使用自定义 bean 定义覆盖集成测试中的 Spring Bean?
【发布时间】:2023-04-04 07:20:01
【问题描述】:

我想重用 Spring 生产上下文配置,但是用另一个替换一些 bean。如果我想用模拟覆盖它们,我会使用@MockBean,它完全符合我的需要(覆盖 bean),但不允许我自己配置​​新的 bean。

我知道还有另一种使用 @ContextConfiguration 的方法,但它对我来说似乎太冗长了。

谢谢。

【问题讨论】:

  • @MockBean 用于测试,而不是用于应用程序代码。
  • 是的,我问的是集成测试(正在加载弹簧上下文的单元测试)
  • 除了定义一个具有相同类型的新bean并将其标记为@Primary之外,没有简单的方法来覆盖bean。 spring.main.allow-bean-definition-overriding=true 不能保证什么 bean 会被覆盖,因为不可预知的配置顺序。另一种方法是从上下文中排除生产 bean(请参阅stackoverflow.com/a/48134123/355438

标签: java spring spring-test


【解决方案1】:

您可以使用@SpyBean - 然后可以针对特定情况对 bean 进行存根(例如 @MockBean 的情况),否则将使用真正的 bean。

另外,如果您确实需要为测试定义自定义 bean 定义,则可以使用 @Primary / @Profile / @ContextConfiguration 的组合来实现此目的。

例如:

@RunWith(SpringRunner.class)
@SpringBootTest
@ActiveProfiles("test")
@ContextConfiguration(classes = {TestConfig.class, ApplicationConfig.class})
public class ApplicatonTest {
    @Profile("test")
    @Configuration
    static class TestConfig {

        @Bean
        @Primary
        public SomeBean testBeanDefinition() {
            SomeBean testBean = new SomeBean();
            // configure SomeBean for test
            return testBean;
        }
    }
    // tests
}

【讨论】:

  • 1) 我是否必须将 ApplicationConfig 中的生产 bean 标记为 !test? 2) 你不认为应该有一个更简单的解决方案吗?
  • 1) 不,不需要将 prod beans 标记为 !test。配置文件覆盖发生。 2)不幸的是,我不知道更简单的方法。通常,当@MockBean 不够用时,@SpyBean 可以解决我的需求。有时我不得不存根@SpyBean 来返回另一个@MockBean@SpyBean(以此类推)。但是,如果您的用例真的要为测试使用自定义 bean 配置,那么据我所知,@Configuration@Primary 是最后的选择。
  • 即使我在生产配置中已经有了@Primary bean,它还能工作吗?
  • 如果候选中恰好存在一个primary bean,它将是自动装配的值。
  • 是的,但是如果我已经有初级 bean 怎么办?例如几乎我所有的服务都使用默认的http客户端(我标记为@Primary),其中一些使用另一个http-client-with-proxy(@Qualifier)。我在单元测试中要覆盖主要的 http 客户端。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-06-08
  • 1970-01-01
  • 1970-01-01
  • 2016-06-15
  • 2018-04-04
  • 2017-02-18
相关资源
最近更新 更多