Junit5 Tests for Spring Email with GreenMail Server using SMTP

4.2k Views Asked by At

I am trying to write JUnit5 tests for Spring Email. When i am running the test , Greenmail server is not receiving any messages. Attaching code snippets for the same:

@ExtendWith(MockitoExtension.class)
public class EmailServiceImplTest {

Mail emailEntity;

GreenMail serverA;

@InjectMocks
private EmailServiceImpl emailService;

@Mock
private JavaMailSender javaMailSender;

@BeforeEach
void setUp() {
    MockitoAnnotations.initMocks(this);
    emailEntity = mockItemMasterData();
    // Setup fake smtp server.
    serverA = new GreenMail(ServerSetupTest.SMTP);
    serverA.start();
}


private Mail mockItemMasterData() {
    Mail mail = new Mail();
    mail.setFrom("[email protected]");
    mail.setTo("[email protected]");
    mail.setSubject("Spring Mail Integration Testing with JUnit and GreenMail Example");
    mail.setBody("We show how to write Integration Tests using Spring and GreenMail.");
    mail.setSendDate(Date.from(Instant.ofEpochSecond(System.currentTimeMillis())));
    return mail;
}

@Test
public void testSendEmailToAvailableMailboxReturnEmail() throws SendFailedException {

    // Using javamailsenderimpl to send the mail.
    emailService.sendSimpleMessage(emailEntity);

    try {
        Message[] messages = serverA.getReceivedMessages();
        Assert.assertNotNull(messages);
        Assert.assertEquals(1, messages.length);
        Assert.assertEquals(emailEntity.getSubject(), messages[0].getSubject());
        Assert.assertEquals(emailEntity.getBody(), String.valueOf(messages[0].getContent()).contains("body"));

    } catch (MessagingException | IOException e) {
        Assert.fail("Should be able to retrive sent mail.");
    }
}

}

And Following is the class for which i am writing this test

@Component
@Slf4j
public class EmailServiceImpl implements EmailService {

@Autowired
private JavaMailSender javaMailSender;

@Override
public void sendSimpleMessage(Mail mail) throws SendFailedException {
    log.info("Send mail started ");
    SimpleMailMessage message = new SimpleMailMessage();
    message.setTo(mail.getTo());
    message.setFrom(mail.getFrom());
    message.setSubject(mail.getSubject());
    message.setText(mail.getBody());
    message.setSentDate(mail.getSendDate());
    javaMailSender.send(message);
    log.info("Send mail end ");
 }
 }

Following is the test yaml source:

---
spring:
 mail:
   default-encoding: UTF-8
   host: localhost
   jndi-name:
   username: username
   password: secret
   port: 2525
   properties:
     mail:
      debug: false
      smtp:
       debug: false
       auth: true
       starttls: true
  protocol: smtp
  test-connection: false

I am able to send email from EmailServiceImpl class but when I am trying to run test , its not getting any mesages.

I tried everything but didn't get any luck. Any help will be really appreciated.

Thanks.

2

There are 2 best solutions below

0
On

Start the server/test in debug mode and see the connection parameters of JavaMailSender (port and host). Accordingly set exactly these parameters in your test yaml file.

2
On

I am able to send email from EmailServiceImpl class but when I am trying to run test , its not getting any messages.

You're not supposed to get messages in test. The low-level component responsible for actual communication with SMTP server is JavaMailSender and in the class EmailServiceImpl you indeed send the actual email by calling:

javaMailSender.send(message);

However in the test you've mocked that class:

@Mock
private JavaMailSender javaMailSender;

So if you put a debugger breakpoint in EmailServiceImpl you'll see that javaMailSender data field contains a mock. Mock is not supposed to send anything, it only allows to specify expectations and verify later. It won't send any actual email.

// in the setup code - setup what do you expect from mock (I assume javaMailSender.send returns void):
 doNothing().when(javaMailSender).send(message);

// in the verification part of the test - make sure that the mock was called once with the params that you expect:
 verify(javaMailSender, times(1)).send(message);

One word about spring just to clarify - in the test you don't use spring at all, so no beans are loaded and no spring configuration available in the yaml file is not actually loaded.