模拟 MIMEMessage 的正确方法?

Posted

技术标签:

【中文标题】模拟 MIMEMessage 的正确方法?【英文标题】:Proper way to mock MIMEMessage? 【发布时间】:2019-04-05 03:02:07 【问题描述】:

我想实际验证消息上设置的字段,例如正文、主题、发件人等...获取 javaMailSender.send(message) 行时总是显示空字段。

是否有模拟 MIMEMessage 的最佳实践?

//EmailService.java

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.mail.javamail.MimeMessageHelper;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;

@Slf4j
public class EmailService 
    private JavaMailSender javaMailSender;

    @Autowired
    public EmailService(JavaMailSender javaMailSender) 
        this.javaMailSender = javaMailSender;
    


    public void sendEmail() 
        MimeMessage message = javaMailSender.createMimeMessage();
        String body = "<html>\n" +
            "<p> This the body </p>\n" +
            "<br>\n";
        try 
            MimeMessageHelper mimeMessageHelper = new MimeMessageHelper(message, true);
            mimeMessageHelper.setSubject("subject");
            mimeMessageHelper.setTo("stack@overflow.com");
            mimeMessageHelper.setFrom("overflow@stack.com");
            mimeMessageHelper.setText(body, true);

            javaMailSender.send(message);

         catch (MessagingException e) 
            log.error("error");
        `enter code here`
    

下面是测试

//EmailServiceTest.java

import org.junit.Before;
import org.junit.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.Mock;
import org.springframework.mail.javamail.JavaMailSender;

import javax.mail.MessagingException;
import javax.mail.internet.MimeMessage;
import java.io.IOException;

import static org.junit.Assert.assertEquals;
import static org.mockito.Mockito.*;
import static org.mockito.MockitoAnnotations.initMocks;


public class EmailServiceTest 
    private EmailService emailService;

    @Mock
    private JavaMailSender javaMailSender;

    @Mock
    private MimeMessage message;

    @Before
    public void setUp() throws IOException 
        initMocks(this);

        emailService = new EmailService(javaMailSender);
    

    @Test
    public void sendEmail_sendsEmailWithCorrectContent() throws MessagingException 
        ArgumentCaptor<MimeMessage> mimeMessageArgumentCaptor = ArgumentCaptor.forClass(MimeMessage.class);
        when(javaMailSender.createMimeMessage()).thenReturn(message);

        doNothing().when(javaMailSender).send(message);

        emailService.sendEmail();

        verify(javaMailSender, times(1)).send((mimeMessageArgumentCaptor.capture()));
        assertEquals("subject", mimeMessageArgumentCaptor.getValue().getSubject());
    


【问题讨论】:

查看这个答案:***.com/a/54836864/5962766 【参考方案1】:

进行这种测试using an integration test 通常更容易。电子邮件通常使用诸如 freemarker 之类的模板库构建,因此集成测试对于能够验证您的模板是否正确也很有价值。

您可以通过使用PowerMock 创建一个模拟MimeMessageHelper 来进行单元测试,但是PowerMock 有时可能无法跟上对其他测试库的更改,并且这样的测试通常会变得脆弱且没有什么价值。例如,您可以验证在 mimeMessageHelper 上调用了 setSubject(),但这是否会产生您真正想要测试的结果(主题设置在 message 上)?

【讨论】:

这个链接很好用,谢谢。我想使用专用的测试工具毕竟是要走的路,而不是单元测试它肯定确实需要更多的部分。

以上是关于模拟 MIMEMessage 的正确方法?的主要内容,如果未能解决你的问题,请参考以下文章

smtp / c# - 使用MimeMessage实例时如何设置回复电子邮件地址

来自 Gmail API 流的 MimeMessage.Load

将 MimeMessage 附加到另一个 MimeMessage

MimeMessage 获取附件名称

如何序列化 Mimemessage 实例?

使用现有的 MimeMessage 对象创建 MimeMessagePreparator