在 Spring Boot 测试中排除配置

Posted

技术标签:

【中文标题】在 Spring Boot 测试中排除配置【英文标题】:Excluding Configuration in Spring boot test 【发布时间】:2018-11-02 18:37:49 【问题描述】:

我在一个 Maven 项目中有以下设置。 生产代码的配置类:

package com.example;
@Configuration
public class MyConfiguration 
    @Bean
    public A beanA() 
      return new A();
    
    ...

然后我有一个测试,它有一个内部Configuration

package com.example;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MyConfiguration.class, SpringConfigurationTest.MyTestConfiguration.class)
public class SpringConfigurationTest 
    @TestConfiguration
    static class MyTestConfiguration 
        @Bean
        @Primary
        public A beanA() 
          return mock(A.class);
            
    

这个类中的测试工作正常。然后我在子包中有另一个测试类:

package com.example.sub;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MyConfiguration.class, AnotherSpringConfigurationTest.MyTestConfiguration.class)
public class AnotherSpringConfigurationTest 
    @TestConfiguration
    static class MyTestConfiguration 
        @Bean
        public B beanB() 
          return new B()
            
    

在此类中运行测试时,还包括来自SpringConfigurationTest.MyTestConfiguration 的测试配置。我猜这是因为包含了位于根目录中的MyConfiguration。效果是在AnotherSpringConfigurationTest 中,bean A 被模拟而不是真实实例。

如何避免其他测试中的配置类被“泄露”到其他测试中?

我看到Spring-boot default profile for integration tests 在 Spring Boot 1.4.1 中使用 Spring 配置文件,而我使用的是 Spring Boot 2.0.1。虽然我确信它可以做到。

我能想到的另一种方法是使用组件扫描来获取上下文并排除所有我不想要的,但这有点麻烦,因为我更喜欢一种我定义我想要的方法使用而不是不应该使用的东西。

Spring Boot 2 是否有一个简单而优雅的解决方案来避免上下文配置冲突?

【问题讨论】:

什么告诉你SpringConfigurationTest.MyTestConfiguration 也包括在内?有什么错误吗? 日志输出表明 bean A 被基于 SpringConfigurationTest.MyTestConfiguration 覆盖,在调试时我可以看到它是模拟而不是真实的。 如何在测试中检索 Bean?与@Autowired ?现在,我看到 2 个 Beans A,你应该有一个 NoUniqueBeanDefinitionException。那你怎么办? 这个例子可能过于简单化了,所以在这些情况下,我会按照你的回答中的建议添加@Primary。但是在AnotherSpringConfigurationTest 中,我希望只有一个bean 定义存在并且来自MyConfiguration 【参考方案1】:

首先,我不喜欢将配置类放在另一个类中的想法。我不知道这是否经常发生,我对Spring有点陌生。但这是我会做的:

第一个配置文件:

@Configuration
@Import(MyConfiguration.class)
public class MyTestConfiguration 
    @Bean
    @Primary // added to let know on @Autowired to use this one instead of the one in first MyConfiguration.class
    public A beanA() 
      return mock(A.class);
        

第二个配置文件:

@Configuration
@Import(MyConfiguration.class)
public class MyOtherTestConfiguration 
    @Bean
    public B beanB() 
      return new B()
        

我不熟悉@TestConfiguration。这就是我使用@Configuration 的原因。

第一个测试课:

package com.example;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MyTestConfiguration.class)
public class SpringConfigurationTest 


第二次测试课:

package com.example.sub;
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = MyOtherTestConfiguration.class)
public class AnotherSpringConfigurationTest 


【讨论】:

我将配置保存在一个单独的文件中,但这并没有改变任何事情。 不是不行,只是不喜欢这个概念。 尝试了使用一种配置并使用@Import 引入其他配置的方法。没用,我认为是因为 Spring boot 不能以这种方式工作,而是将配置作为 root 来扫描更多的 bean,这些配置是一种。 我尝试了您提供的设置,并且没有问题。所以我认为问题不在于您的测试设置。

以上是关于在 Spring Boot 测试中排除配置的主要内容,如果未能解决你的问题,请参考以下文章

Java Spring Boot 测试:如何从测试上下文中排除 java 配置类

从 Spring-Boot 测试中排除 elasticsearchTemplate

从 Spring Boot 单元测试中排除 Spring Cloud Config Server

译:从 JSON 文件加载 Spring Boot 属性

Spring Boot 排除自动配置的4个方法

spring boot 依赖排除