模拟 MIMEMessage 的正确方法?
Proper way to mock MIMEMessage?
我想实际验证消息上设置的字段,如正文、主题、发件人等……我也尝试过使用参数捕捉器,但没有用,当我调试代码时,消息在获取 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());
}
}
进行这种测试通常更容易 using an integration test。电子邮件通常是使用 freemarker 等模板库构建的,因此集成测试对于验证您的模板是否正确也很有价值。
您可以通过使用 PowerMock 创建模拟 MimeMessageHelper
来进行单元测试,但 PowerMock 有时在跟上其他测试库的变化方面可能很慢,并且此类测试通常最终会变得脆弱而且价值不大。例如,您可以验证 setSubject()
在 mimeMessageHelper
上被调用,但这是否会产生您真正想要测试的结果(主题在 message
上设置)?
我想实际验证消息上设置的字段,如正文、主题、发件人等……我也尝试过使用参数捕捉器,但没有用,当我调试代码时,消息在获取 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());
}
}
进行这种测试通常更容易 using an integration test。电子邮件通常是使用 freemarker 等模板库构建的,因此集成测试对于验证您的模板是否正确也很有价值。
您可以通过使用 PowerMock 创建模拟 MimeMessageHelper
来进行单元测试,但 PowerMock 有时在跟上其他测试库的变化方面可能很慢,并且此类测试通常最终会变得脆弱而且价值不大。例如,您可以验证 setSubject()
在 mimeMessageHelper
上被调用,但这是否会产生您真正想要测试的结果(主题在 message
上设置)?