Spring 在测试期间从包私有类获取配置

Posted

技术标签:

【中文标题】Spring 在测试期间从包私有类获取配置【英文标题】:Spring gets config from package-private class during test 【发布时间】:2019-06-19 11:26:40 【问题描述】:

我从 Spring 2.0 更新到 Spring boot 2.1 并且我的服务测试失败。

我的测试结构:

com
  ...
    service
      ServiceTest.java
    web
      ControllerTest.java

ServiceTest.java:

@ExtendWith(SpringExtension.class)
@DataJpaTest
public class ServiceTest 

    @Autowired
    private OtherService otherService;

    ...


ControllerTest.java:

@ExtendWith(SpringExtension.class)
@WebMvcTest(secure = false)
@Import(WebMvcConfig.class)
@SuppressWarnings("Duplicates")
public class GroupControllerTest 

    @Configuration
    static class Config 
        @Bean
        public Controller controller() 
            return new Controller();
        
    

在 ServiceTest 期间出现错误:

原因: org.springframework.beans.factory.support.BeanDefinitionOverrideException: 类路径中定义的名称为“控制器”的无效 bean 定义 资源 [com/.../web/ControllerTest$Config.class]

spring 如何从 GroupControllerTest 的内部包私有类中获取 ServiceTest 的配置? 有点奇怪!为什么要扫描兄弟目录进行配置?

【问题讨论】:

【参考方案1】:

这是 Spring TestContext Framework 中的预期行为。如果您没有明确指定要使用哪个@Configuration 类(或多个类),Spring 将在当前测试类中查找静态嵌套类。

以下是Spring参考手册Testing chapter的摘录。

如果您从 @ContextConfiguration 注释中省略 classes 属性,TestContext 框架会尝试检测默认配置类的存在。具体来说,AnnotationConfigContextLoaderAnnotationConfigWebContextLoader 检测测试类的所有静态嵌套类,这些类满足@Configuration javadoc 中指定的配置类实现的要求。请注意,配置类的名称是任意的。此外,如果需要,一个测试类可以包含多个静态嵌套配置类。

由于您使用的是 Spring Boot,因此您应该使用 @SpringBootTest 注释您的测试类,以便让 Spring Boot 找到您的 @Configuration 类。

【讨论】:

我明白这一点,但是通过 spring 从其他类的静态内部类获取配置,而不是当前的? 核心 Spring 中的 Spring TestContext Framework 不会扫描除当前测试类之外的任何类中的静态嵌套类。 因此,必须有其他东西通过组件扫描拉入该类。也许是您的 @Configuration 类或 Spring Boot 之一。 如果你用@SpringBootTest注释ServiceTest会发生什么? 感谢您对组件扫描的看法。我有 @SpringBootApplication 和 @ComponentScan(...) 扫描我所有的包,但我没有意识到它也会影响测试包。所以我需要重构)

以上是关于Spring 在测试期间从包私有类获取配置的主要内容,如果未能解决你的问题,请参考以下文章

在测试期间注入@Autowired 私有字段

Spring Boot 自动装配配置类进入 Junit 测试

获取Typescript中所有私有成员列表的方法?

获取SPRING 代理对象的真实实例,可以反射私有方法,便于测试

H2 嵌入式数据库在 Spring Boot 测试期间未获取属性

在单元测试期间填充 Spring @Value