Reputation: 4018
I have a service that has injected the JavaMailSender. My service configures it and sends a mail. I'd like to intercept the raw mail to ensure the information is the correct. I'd like to do that in a JUnit.
How would you guys do that?
@Service
public class MyServiceImpl {
@Autowired
private JavaMailSender _mailSender;
public void sendMail(String to, String body, String subject){
...
_mailSender.something
...
}
}
Upvotes: 21
Views: 34636
Reputation: 6513
Elaborating on @justinas-jakavonis answer I would suggesto to include this configuration bean in your src/test/java
@Configuration
public class JavaMailSenderTestConfiguration {
private JavaMailSender javaMailSender;
private MimeMessage mimeMessage;
@Bean
JavaMailSender mockMailSender() {
mimeMessage = Mockito.mock(MimeMessage.class);
javaMailSender = Mockito.mock(JavaMailSender.class);
Mockito.when(javaMailSender.createMimeMessage()).thenReturn(mimeMessage);
return javaMailSender;
}
}
Upvotes: 0
Reputation: 1
Regarding test with GreenMail, you don't want any end to end encryption as it's in your local machine, and for that you need to add this properties to your application-test.properties
file:
spring:
mail:
username: [email protected]
password: *********
host: 127.0.0.1
port: 3025
protocol: smtp
test-connection: false
properties:
mail:
smtp:
starttls:
required: false
enable: false
Otherwise you'll get an error: STARTTLS is required but host does not support STARTTLS.
Upvotes: 0
Reputation: 12021
To add a more recent answer to this question and as the linked blog post from 2012 seems to be down occasionally, here's a full example of using GreenMail for writing integration tests with JUnit 5 (assuming you're using Spring Boot's auto-configuration for the JavaMailSender
).
First, make sure to override the credentials and location of the mail server. You can add an application.yml
file inside src/test/resources
for this purpose:
spring:
mail:
password: springboot
username: duke
host: 127.0.0.1
port: 3025 # default protocol port + 3000 as offset
protocol: smtp
test-connection: true
Next, Spring Boot's auto-configuration will configure the JavaMailSender
to connect to GreenMail for your tests. You can use GreenMail's JUnit Jupiter extension to conveniently start/stop a GreenMail server for your tests:
<dependency>
<groupId>com.icegreen</groupId>
<artifactId>greenmail-junit5</artifactId>
<version>1.6.1</version>
<scope>test</scope>
</dependency>
... resulting in the following sample test:
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class JavaMailSenderIT {
@RegisterExtension
static GreenMailExtension greenMail = new GreenMailExtension(ServerSetupTest.SMTP)
.withConfiguration(GreenMailConfiguration.aConfig().withUser("duke", "springboot"))
.withPerMethodLifecycle(false);
@Autowired
private JavaMailSender javaMailSender;
@Test
void shouldUseGreenMail() throws Exception {
SimpleMailMessage mail = new SimpleMailMessage();
mail.setFrom("[email protected]");
mail.setSubject("A new message for you");
mail.setText("Hello GreenMail!");
mail.setTo("[email protected]");
javaMailSender.send(mail);
// awaitility
await().atMost(2, SECONDS).untilAsserted(() -> {
MimeMessage[] receivedMessages = greenMail.getReceivedMessages();
assertEquals(1, receivedMessages.length);
MimeMessage receivedMessage = receivedMessages[0];
assertEquals("Hello GreenMail!", GreenMailUtil.getBody(receivedMessage));
assertEquals(1, receivedMessage.getAllRecipients().length);
assertEquals("[email protected]", receivedMessage.getAllRecipients()[0].toString());
});
}
}
You can also use Testcontainers to start a local GreenMail container as your local sandbox email server.
Upvotes: 4
Reputation: 21381
I've done it using GreenMail. Take a look at my blog post about it where you'll also find a working example.
Upvotes: 26
Reputation: 8798
If your goal is to use just Junit/Mockito and test how MimeMessage was formed before sending then the configuration below should be sufficient:
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());
}
}
Upvotes: 3
Reputation: 5070
You can use a test SMTP server, like Dumbster. See the example below:
@Test
public void sendSimpleEmailWithCC() {
// Runs a Dumbster simple SMTP server - default config
SimpleSmtpServer server = SimpleSmtpServer.start();
String from = "[email protected]";
String to = "[email protected]";
String messageText = "Good message";
String title = "Test message";
String cc = "[email protected]";
Assert.assertTrue(mailSender
.sendEmail(from, to, cc, title, messageText));
server.stop();
Assert.assertTrue(server.getReceivedEmailSize() == 1);
Iterator emailIter = server.getReceivedEmail();
SmtpMessage email = (SmtpMessage) emailIter.next();
Assert.assertTrue(email.getHeaderValue("From").equals(from));
Assert.assertTrue(email.getHeaderValue("To").equals(to));
Assert.assertTrue(email.getHeaderValue("Cc").equals(cc));
Assert.assertTrue(email.getHeaderValue("Subject")
.equals("Test message"));
Assert.assertTrue(email.getBody().equals(messageText));
}
Upvotes: 5