SpringBoot中如何将application.properties的@Value属性注入@InjectMocks对象
问题根因
- 你使用的
PowerMockRunner默认不会启动Spring上下文,所有@Value注解都不会被Spring处理,测试类中定义的priorMap本身就是null,即便反射没有报错也无法注入有效值。 - 抛出的模块访问错误是高版本JDK(9+)的模块化限制导致的,PowerMock依赖的旧版XML解析库尝试访问JDK内部未导出的
jdk.xml.internal包。 - 现有代码存在逻辑错误:BatchService中的
priorMap是实例字段,不是静态字段,你在静态@BeforeClass方法中给类的静态字段赋值,就算没有报错,也不会生效到你测试用的batchService实例上。
可行解决方案(按推荐优先级排序)
方案1:直接手动赋值(最轻量,单元测试首选)
单元测试不需要加载Spring上下文,直接手动构造Map给实例赋值即可,完全避开兼容性问题:
@RunWith(PowerMockRunner.class) @PrepareForTest({LogManager.class}) public class BatchServiceTest { @Mock private Repo repoMock; @InjectMocks private BatchService batchService; @Before public void setup() { // 构造和配置文件一致的映射 Map<String, String> priorMap = Map.of("first", "1", "second", "2", "third", "3"); // 因为priorMap是public修饰,直接赋值即可,无需反射 batchService.priorMap = priorMap; // 如果priorMap是private,改用下面的反射写法即可 // ReflectionTestUtils.setField(batchService, "priorMap", priorMap); } // 你的测试用例 }
方案2:手动加载配置文件(不想硬编码配置时使用)
如果不想把配置值硬编码在测试类中,可以手动读取classpath下的application.properties解析:
@RunWith(PowerMockRunner.class) @PrepareForTest({LogManager.class}) public class BatchServiceTest { @Mock private Repo repoMock; @InjectMocks private BatchService batchService; @Before public void setup() throws IOException { // 加载配置文件 Properties properties = new Properties(); properties.load(getClass().getResourceAsStream("/application.properties")); String mappingStr = properties.getProperty("priority.mapping"); // 解析映射字符串为Map,此处用Jackson做JSON解析,也可替换为其他JSON工具 ObjectMapper objectMapper = new ObjectMapper(); Map<String, String> priorMap = objectMapper.readValue( mappingStr.replace("'", "\""), new TypeReference<Map<String, String>>() {} ); batchService.priorMap = priorMap; } // 你的测试用例 }
方案3:兼容Spring上下文+修复模块报错(必须用@Value注解时使用)
如果你一定要依赖Spring的@Value能力注入配置,需要调整测试类启动Spring上下文,同时修复JDK模块兼容问题:
- 调整测试类注解,用PowerMock委托SpringRunner启动上下文:
@RunWith(PowerMockRunner.class) @PowerMockRunnerDelegate(SpringRunner.class) @SpringBootTest @PrepareForTest({LogManager.class}) public class BatchServiceTest { @Value("#{${priority.mapping}}") private Map<String, String> priorMap; @MockBean private Repo repoMock; @Autowired private BatchService batchService; @Before public void setup() { // 此时priorMap已经被Spring注入有效值,直接赋值即可 batchService.priorMap = priorMap; } // 你的测试用例 }
- 解决JDK模块报错,给单元测试的JVM启动参数添加如下配置:
--add-exports java.xml/jdk.xml.internal=ALL-UNNAMED
如果是Maven项目,在pom.xml的surefire插件中统一配置:
<plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-surefire-plugin</artifactId> <configuration> <argLine>--add-exports java.xml/jdk.xml.internal=ALL-UNNAMED</argLine> </configuration> </plugin>
内容的提问来源于stack exchange,提问作者Saqib Nisar
相关产品推荐
相关产品推荐

