You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring Boot邮件测试问题:如何从message.properties读取邮件主题与内容

Spring Boot 邮件发送测试用例:从message.properties读取内容的正确姿势

问题根源

你直接把属性键字符串"event.appointment.slot.user.repeat"赋值给邮件主题,Spring不会自动解析成对应的属性值;而错误使用$[0].code语法,这不是Spring读取属性的正确方式。

解决方案步骤

1. 确保MessageSource配置正确

Spring Boot默认会自动加载src/main/resources下的message.properties,如果需要自定义位置或编码,可在application.properties中配置:

spring.messages.basename=messages
spring.messages.encoding=UTF-8

2. 在邮件发送类中注入并使用MessageSource

通过构造器注入MessageSource,调用其getMessage()方法读取属性值,支持动态参数替换:

import org.springframework.context.MessageSource;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Component;

@Component
public class EmailService {

    private final JavaMailSender emailSender;
    private final MessageSource messageSource;

    public EmailService(JavaMailSender emailSender, MessageSource messageSource) {
        this.emailSender = emailSender;
        this.messageSource = messageSource;
    }

    public void sendCancellationEmail(Doctor doctor, EventData eventData) {
        SimpleMailMessage message1 = new SimpleMailMessage();
        message1.setFrom("develop@gmail.com");
        message1.setTo(doctor.getEmail());
        
        // 读取主题属性值,无参数时传null
        String subject = messageSource.getMessage("event.appointment.cancelled", null, null);
        message1.setSubject(subject);
        
        // 先在message.properties中定义带占位符的文本:
        // event.appointment.cancelled.text=You have one {0} appointment at {1} to {2} was cancelled by patient.
        String text = messageSource.getMessage("event.appointment.cancelled.text", 
                new Object[]{eventData.getTitle(), eventData.getStart(), eventData.getEnd()}, null);
        message1.setText(text);
        
        emailSender.send(message1);
    }
}

3. 编写测试用例

方式1:完整上下文集成测试

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.test.context.TestPropertySource;
import static org.mockito.Mockito.*;

@SpringBootTest
// 配置测试用邮件服务器,避免真实发送邮件
@TestPropertySource(properties = {
        "spring.mail.host=localhost",
        "spring.mail.port=1025",
        "spring.mail.username=test",
        "spring.mail.password=test"
})
public class EmailServiceTest {

    @Autowired
    private EmailService emailService;
    
    @Autowired
    private JavaMailSender emailSender;

    @Test
    public void testSendCancellationEmail() {
        // 构造测试数据
        Doctor doctor = new Doctor();
        doctor.setEmail("doctor@test.com");
        
        EventData eventData = new EventData();
        eventData.setTitle("General Checkup");
        eventData.setStart("2024-05-20 10:00");
        eventData.setEnd("2024-05-20 11:00");
        
        // 执行发送逻辑
        emailService.sendCancellationEmail(doctor, eventData);
        
        // 验证邮件发送行为
        verify(emailSender, times(1)).send(any(SimpleMailMessage.class));
    }
}

方式2:Mock依赖的单元测试

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.jupiter.MockitoExtension;
import org.springframework.context.MessageSource;
import org.springframework.mail.javamail.JavaMailSender;
import static org.mockito.Mockito.*;

@ExtendWith(MockitoExtension.class)
public class EmailServiceUnitTest {

    @Mock
    private JavaMailSender emailSender;
    
    @Mock
    private MessageSource messageSource;
    
    @InjectMocks
    private EmailService emailService;

    @Test
    public void testSendCancellationEmail() {
        // Mock MessageSource的返回值
        when(messageSource.getMessage("event.appointment.cancelled", null, null))
                .thenReturn("Appointment Canceled.");
        when(messageSource.getMessage("event.appointment.cancelled.text", 
                new Object[]{"General Checkup", "2024-05-20 10:00", "2024-05-20 11:00"}, null))
                .thenReturn("You have one General Checkup appointment at 2024-05-20 10:00 to 2024-05-20 11:00 was cancelled by patient.");
        
        // 构造测试数据
        Doctor doctor = new Doctor();
        doctor.setEmail("doctor@test.com");
        
        EventData eventData = new EventData();
        eventData.setTitle("General Checkup");
        eventData.setStart("2024-05-20 10:00");
        eventData.setEnd("2024-05-20 11:00");
        
        // 执行发送逻辑
        emailService.sendCancellationEmail(doctor, eventData);
        
        // 验证邮件发送行为
        verify(emailSender, times(1)).send(any(SimpleMailMessage.class));
    }
}

关键注意点

  • 禁止直接将属性键赋值给邮件主题/文本,必须通过MessageSource.getMessage()获取解析后的值
  • 需要动态替换内容时,在message.properties中用{0}、{1}占位符,调用getMessage时传入对应参数数组
  • 测试时可通过Mock工具模拟MessageSource或JavaMailSender,避免触发真实邮件发送

内容的提问来源于stack exchange,提问作者Preethi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 07:45:35