How to test JavaMailSender?
Solution 1
You can test how MimeMessage
was formed with:
public class EmailServiceTest {
private EmailServiceImpl emailServiceImpl;
private JavaMailSender javaMailSender;
private MimeMessage mimeMessage;
@Before
public void before() {
mimeMessage = new MimeMessage((Session)null);
javaMailSender = mock(JavaMailSender.class);
when(javaMailSender.createMimeMessage()).thenReturn(mimeMessage);
emailServiceImpl = new EmailService(javaMailSender);
}
@Test
public void emailTest() {
String recipient = "[email protected]"
EmailRequest request = new EmailRequest();
request.setRecipient(recipient);
emailServiceImpl.send(request);
assertEquals(recipient, mimeMessage.getRecipients(RecipientType.TO)[0].toString());
}
}
Solution 2
I think you are getting unit test / mocking wrong. It seems that you want to create a unit test; but expect the results of a integration test.
What you can do with a unit test here:
- provide a mocked JavaMailSender (as you already)
- use verify on that mock later on
In other words: you are mocking the actual sending of a mail. Thus you can't expect that a mail will show up somewhere!
The only thing possible: ensure that the method calls you expect to see actually take place. But that basically leads you to write a test case that simply "re-implements" your production code using verify calls. That isn't too helpful.
Probably you should rather look into a real integration test here. Send a real email; and check a real inbox if that mail shows up there.
Solution 3
I use Mockito
to mock a JavaMailSender
bean and instantiate it in a class annotated with @Configuration
that runs only using a test profile:
import static org.mockito.Mockito.*;
import javax.mail.Session;
import javax.mail.internet.MimeMessage;
import org.springframework.context.annotation.*;
import org.springframework.mail.javamail.JavaMailSender;
@Profile("test")
@Configuration
public class EmailServiceTest {
@Bean
@Primary
public JavaMailSender javaMailSender() {
JavaMailSender javaMailSender = mock(JavaMailSender.class);
when(javaMailSender.createMimeMessage()).thenReturn(new MimeMessage((Session) null));
return javaMailSender;
}
}
Mar Mosh
Updated on July 26, 2022Comments
-
Mar Mosh over 1 year
I have little problem. I created MailService to send mails. When I run program, it works. All properties to email I have in
resources/application.properties
. I'm usingspring-boot-starter-mail
.@Service public class MailService { private JavaMailSender javaMailSender; @Autowired public MailService(JavaMailSender javaMailSender) { this.javaMailSender = javaMailSender; } public void sendMail(String subject, String messageContent, String recipient) throws MessagingException { MimeMessage mimeMessage = javaMailSender.createMimeMessage(); MimeMessageHelper messageHelper = new MimeMessageHelper(mimeMessage); messageHelper.setTo(recipient); messageHelper.setSubject(subject); messageHelper.setText(messageContent); javaMailSender.send(mimeMessage); } }
But I don't have idea how can I create test for it. I tried something like this, where I use
org.jvnet.mock-javamail:mock-javamail
, but it doesn't work:public class MailServiceTest { private MailService mailService; @Mock private JavaMailSender javaMailSender; @Before public void setUp() { MockitoAnnotations.initMocks(this); mailService = new MailService(javaMailSender); Mailbox.clearAll(); } @Test public void sendMailTest() throws MessagingException, IOException { String subject = "Some subject"; String body = "Some contents."; String recipient = "[email protected]"; mailService.sendMail(subject, body, recipient); List<Message> inbox = Mailbox.get(recipient); assertTrue(inbox.size() == 1); assertEquals(subject, inbox.get(0).getSubject()); assertEquals(body, inbox.get(0).getContent()); } }