@SpringBootTest中显式声明JavaMailSender Bean仍自动注入为null如何解决
问题根因与解决方案
1 首要原因:注入时机错误
你在类属性定义阶段直接初始化MailService,此时Spring还未完成@Autowired字段的注入操作,javaMailSender还处于null状态,自然传给MailService的参数也是null。
Spring的字段注入逻辑是在测试类实例化完成之后才执行的,类属性的初始化操作是在实例化过程中执行的,顺序早于注入。
2 次要排查点:配置类未被加载
如果调整时机后还是null,说明你的MailSenderTestConfiguration没有被Spring Boot的测试扫描逻辑识别到,默认@SpringBootTest只会扫描启动类所在包、测试类所在包及其子包下的配置类,路径不匹配就不会创建对应的Bean。
修复步骤
方案一:使用构造注入(推荐)
Spring Boot 4.3+版本支持测试类构造参数自动注入,直接在构造阶段完成MailService初始化即可:
@SpringBootTest(classes = MailSenderTestConfiguration.class) // 显式指定加载配置类,避免扫描问题 class MailServiceTest { private final JavaMailSender javaMailSender; private final MailService mailService; private final GreenMail greenMail = new GreenMail(); public MailServiceTest(@Qualifier("testJavaMailSender") JavaMailSender javaMailSender) { this.javaMailSender = javaMailSender; this.mailService = new MailService(javaMailSender); } @BeforeEach public void setup() { greenMail.setUser("foo@localhost", "foo", "password"); greenMail.start(); } @AfterEach public void teardown() { greenMail.stop(); } @Test public void shouldSendNotificationEmailToRecipient() { final String expectedText = "An error occured while executing the Jira Connector import sync." + "Please see the log file: 'jira-connector.log' in the application directory"; mailService.notifyAdmin(); final MimeMessage[] receivedMessage = greenMail.getReceivedMessagesForDomain("my-ag.com"); final String actual = GreenMailUtil.getBody(receivedMessage[0]); assertThat(actual).isEqualTo(expectedText); } }
方案二:调整初始化时机到@BeforeEach
也可以把MailService的初始化放到@BeforeEach方法中,此时Spring已经完成了所有字段注入:
@SpringBootTest(classes = MailSenderTestConfiguration.class) class MailServiceTest { @Autowired @Qualifier("testJavaMailSender") private JavaMailSender javaMailSender; private MailService mailService; private final GreenMail greenMail = new GreenMail(); @BeforeEach public void setup() { this.mailService = new MailService(javaMailSender); greenMail.setUser("foo@localhost", "foo", "password"); greenMail.start(); } // 其余代码保持不变 }
额外注意点
你当前配置的JavaMailSender指向了真实的Gmail SMTP服务器,测试邮件不会进入GreenMail,会导致后续收不到测试邮件断言失败,需要修改配置类的Bean参数适配GreenMail:
@Configuration class MailSenderTestConfiguration { @Bean(name = "testJavaMailSender") public JavaMailSender testJavaMailSender() { JavaMailSenderImpl mailSender = new JavaMailSenderImpl(); // 替换为GreenMail的本地服务配置,默认SMTP端口为3025 mailSender.setHost("localhost"); mailSender.setPort(3025); mailSender.setUsername("foo@localhost"); mailSender.setPassword("password"); Properties props = mailSender.getJavaMailProperties(); props.put("mail.transport.protocol", "smtp"); props.put("mail.smtp.auth", "true"); props.put("mail.smtp.starttls.enable", "true"); props.put("mail.debug", "true"); return mailSender; } }
内容的提问来源于stack exchange,提问作者xetra11
相关产品推荐
相关产品推荐

