使用@SpringJUnitConfig替代@SpringBootTest时的依赖与配置异常问题
解决@SpringJUnitConfig替代@SpringBootTest时的Bean注入与属性解析问题
核心问题分析
替换后出现的一系列问题本质是**@SpringJUnitConfig与@SpringBootTest的启动逻辑差异**:
- @SpringBootTest会自动触发组件扫描、加载Spring Boot自动配置、读取默认配置文件(application.yml/properties);
- @SpringJUnitConfig仅负责加载指定的配置类,不会自动执行上述Spring Boot特有的初始化逻辑。
分步解决方案
1. 解决NoSuchBeanDefinitionException(无法注入@Service)
需要显式指定组件扫描范围,让Spring能找到DataMarshallerService:
- 在测试类上添加
@ComponentScan,指定目标Service所在的包; - 或者在自定义配置类中添加
@ComponentScan,再通过@SpringJUnitConfig指定该配置类。
2. 解决属性解析失败(${sftp.in.port}无法解析)
@SpringJUnitConfig默认不支持YAML配置文件加载,也不会自动启用Spring Boot的属性解析机制,需手动配置:
- 自定义
YamlTestPropertySourceFactory来加载YAML文件; - 结合
@SpringBootConfiguration或@EnableConfigurationProperties启用Spring Boot属性处理逻辑。
完整配置示例
方案一:测试类直接配置(推荐,更简洁)
import org.springframework.boot.test.context.SpringBootConfiguration; import org.springframework.context.annotation.ComponentScan; import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; import org.springframework.test.context.TestPropertySource; @SpringJUnitConfig // 启用Spring Boot配置基础能力 @SpringBootConfiguration // 扫描DataMarshallerService所在的包,替换为你的实际包路径 @ComponentScan(basePackages = "com.yourproject.service") // 加载测试用YAML配置,指定自定义Factory处理YAML @TestPropertySource( locations = "classpath:application-test.yml", factory = YamlTestPropertySourceFactory.class ) public class DataMarshallerServiceTest { @Autowired private DataMarshallerService dataMarshallerService; // 测试方法... }
自定义YAML属性源Factory
import org.springframework.beans.factory.config.YamlPropertiesFactoryBean; import org.springframework.core.env.PropertiesPropertySource; import org.springframework.core.env.PropertySource; import org.springframework.core.io.support.EncodedResource; import org.springframework.core.io.support.PropertySourceFactory; import java.io.IOException; import java.util.Properties; public class YamlTestPropertySourceFactory implements PropertySourceFactory { @Override public PropertySource<?> createPropertySource(String name, EncodedResource resource) throws IOException { YamlPropertiesFactoryBean factory = new YamlPropertiesFactoryBean(); factory.setResources(resource.getResource()); Properties properties = factory.getObject(); // 生成属性源名称,为空则用文件名 String sourceName = name != null ? name : resource.getResource().getFilename(); return new PropertiesPropertySource(sourceName, properties); } }
方案二:自定义配置类(更精准控制)
如果需要更细粒度的配置控制,可以创建测试专属配置类:
// 测试配置类 import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.boot.context.properties.EnableConfigurationProperties; @Configuration @ComponentScan(basePackages = "com.yourproject.service") // 启用配置属性绑定(如果你的项目用了@ConfigurationProperties) @EnableConfigurationProperties(SftpProperties.class) // 加载YAML配置,指定自定义Factory @PropertySource( value = "classpath:application-test.yml", factory = YamlTestPropertySourceFactory.class ) public class TestAppConfig { // 若需手动注册属性解析器(Spring Boot 2.2+ 通常无需此步骤) /* @Bean public static PropertySourcesPlaceholderConfigurer propertyConfigurer() { return new PropertySourcesPlaceholderConfigurer(); } */ } // 测试类 @SpringJUnitConfig(classes = TestAppConfig.class) public class DataMarshallerServiceTest { @Autowired private DataMarshallerService dataMarshallerService; // 测试方法... }
关键注意事项
- 确保
application-test.yml放置在src/test/resources目录下,保证能被类路径扫描到; - 若项目使用
@ConfigurationProperties绑定属性,需确保对应的配置类被@EnableConfigurationProperties或@Component标记; - 如果不需要精准控制,也可以直接在
@SpringJUnitConfig上添加@EnableAutoConfiguration,但会加载所有Spring Boot自动配置,可能失去使用@SpringJUnitConfig的轻量化意义。
内容的提问来源于stack exchange,提问作者Simeon Leyzerzon
相关产品推荐
相关产品推荐

