How to test JavaMailSender?

16,672

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;
    }
}
Share:
16,672
Mar Mosh
Author by

Mar Mosh

Updated on July 26, 2022

Comments

  • Mar Mosh
    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 using spring-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());
        }
    }