Spring Boot JUnit测试时Service注入的MessageSource为空或找不到对应消息问题
问题根因
- 如果你使用
@WebMvcTest、@ServiceTest这类切片测试注解做JUnit测试,Spring默认只会加载对应切片范围内的组件,不会触发MessageSource的自动配置,此时注入的是空实现EmptyMessageSource,所以会报空MessageSource错误,这也是生产运行正常但测试报错的核心原因。 - 你手动在启动类定义
MessageSourceBean时没有正确配置资源文件路径、编码等参数,也没有关联生效的父消息源,所以即使不再报空实现错误,也找不到对应code的消息内容。
解决方案
方案1:集成测试直接加载完整上下文
如果你的测试属于需要加载全量Spring组件的集成测试,直接给测试类添加@SpringBootTest注解即可,Spring Boot会自动加载和生产环境完全一致的MessageSource配置,无需额外手动定义Bean,示例代码如下:
// JUnit5 示例 @SpringBootTest class ServiceATest { @Autowired private ServiceA serviceA; @Test void testMethod() { // 调用测试方法 serviceA.method(); } }
方案2:切片测试主动导入MessageSource自动配置
如果你使用切片测试不想加载完整上下文,可以在测试类上添加@ImportAutoConfiguration(MessageSourceAutoConfiguration.class)注解,主动导入消息源的自动配置,即可拿到和生产环境一致的实例:
@ServiceTest(ServiceA.class) @ImportAutoConfiguration(MessageSourceAutoConfiguration.class) class ServiceATest { @Autowired private ServiceA serviceA; @Test void testMethod() { serviceA.method(); } }
方案3:手动定义MessageSource的正确配置
如果你确实需要自定义MessageSource Bean,按照如下规则配置即可解决找不到code的问题:
@Bean public MessageSource messageSource() { ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource(); // 配置资源文件路径,多个路径用逗号分隔,默认前缀是classpath:messages messageSource.setBasenames("classpath:messages", "classpath:i18n/common-messages"); // 配置编码避免中文乱码 messageSource.setDefaultEncoding("UTF-8"); // 找不到code时返回code本身而非抛出异常,可按需开启 messageSource.setUseCodeAsDefaultMessage(true); return messageSource; }
配置完成后如果仍然找不到对应code,检查两个点:
- 测试模块的
resources目录下是否存在对应语言的配置文件,比如messages_zh_CN.properties - 配置文件中的key和你调用
getMessage传入的messageKey是否完全一致,注意大小写和特殊字符
内容的提问来源于stack exchange,提问作者Anshul
相关产品推荐
相关产品推荐

