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

Spring Boot中JUnit+Mockito测试Thymeleaf邮件模板报空指针问题排查

解决Thymeleaf邮件测试的NullPointerException问题

问题根源分析

  1. TemplateEngine为空:你的测试类用@Autowired注入TemplateEngine,但单元测试默认不会启动Spring上下文,导致这个实例是null,调用templateEngine.process()时直接抛出NPE。
  2. helper未初始化:setUp方法里的helper变量只声明了,没创建实例就调用helper.setText(),这也是NPE的直接触发点。
  3. 不必要的模板渲染调用:测试阶段不需要实际渲染Thymeleaf模板,应该Mock这个方法的返回值,隔离外部依赖。

修复步骤

  1. 把TemplateEngine改成Mock对象,用@Mock注解替代@Autowired,让Mockito生成Mock实例,避免null。
  2. 移除setUp里冗余的templateEngine.process()和helper.setText()代码,这些逻辑属于被测试方法的内部实现,测试时不需要提前执行。
  3. MocktemplateEngine.process()方法,返回一个模拟的HTML字符串,不用依赖实际模板文件。
  4. 添加Mockito的扩展注解,确保Mock对象正常初始化(JUnit 5用@ExtendWith(MockitoExtension.class),JUnit 4用@RunWith(MockitoJUnitRunner.class))。

修改后的测试类代码

import org.junit.jupiter.api.BeforeEach;
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 javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.time.LocalDateTime;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.mockito.Mockito.when;

@ExtendWith(MockitoExtension.class)
public class EmailServiceImplTest {

    @Mock
    private JavaMailSender javaMailSender;

    @Mock
    private TemplateEngine templateEngine;

    @InjectMocks
    private EmailServiceImpl emailServiceImpl;

    private MimeMessage mimeMessage;
    private String email;
    private Employee employee;

    @BeforeEach
    public void setUp() {
        // 初始化测试数据
        employee = new Employee("John Smith",
                20.0,"AB243", "A","B",
                LocalDateTime.now().plusDays(2),20);
        mimeMessage = new MimeMessage((Session)null);
        email = "someone@gmail.com";

        // Mock TemplateEngine的process方法,返回模拟的HTML内容
        when(templateEngine.process("/email", org.thymeleaf.context.Context.class))
                .thenReturn("<html><body>Hello John Smith</body></html>");
        // Mock JavaMailSender创建MimeMessage的方法
        when(javaMailSender.createMimeMessage()).thenReturn(mimeMessage);
    }

    @Test
    public void emailTest() throws MessagingException {
        emailServiceImpl.sendEmail(employee, email);
        assertEquals(email, mimeMessage.getRecipients(MimeMessage.RecipientType.TO)[0].toString());
    }
}

额外说明

  • 单元测试的核心是隔离依赖,所以所有外部依赖(JavaMailSender、TemplateEngine)都应该用Mock对象替代,避免依赖实际的Spring上下文或文件系统中的模板。
  • 如果需要测试Thymeleaf模板的渲染逻辑,可以单独写一个测试类,加载Spring上下文并注入真实的TemplateEngine,专门验证模板渲染结果,但这属于集成测试范畴,不是单元测试。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 11:36:14