Mock Javamail primer
Small primer for mock javamail, a pretty useful project that will be handy whenever you need to test code that uses POP3/IMAP/SMTP and you wouldn't like to build wrappers for anything you need to test - javamail does not really offer interfaces that can be implemented by mock objects, but different implementations can be used at runtime depending on which jars are on the classpath.
Take a look at the project homepage:
http://java.net/projects/mock-javamail
Be sure you've enabled java.net Maven repo, and add this dependency to your pom.xml:
1 <dependency>
2 <groupId>org.jvnet.mock-javamail</groupId>
3 <artifactId>mock-javamail</artifactId>
4 <version>1.9</version>
5 <scope>test</scope>
6 </dependency>
You're almost ready; now setup your test code this way:
1 public class IMAPMailRepositoryTest {
2 @Before
3 public void setUp() throws Exception {
4 final Session session = Session.getInstance(
5 System.getProperties());
6
7 MimeMessage msg = new MimeMessage(
8 session);
9 msg.setRecipients(Message.RecipientType.TO,
10 "testuser@mockserver.com");
11 msg.setSubject("Some Subject");
12 msg.setText("sometext");
13 Transport.send(msg);
14 }
15
16 @After
17 public void tearDown() throws Exception {
18 Mailbox.clearAll();
19 }
Now you're ready to use your mock javamail:
1 public class SomeImapClient {
2
3 private static Logger log = Logger.getLogger(SomeImapClient.class);
4
5 public void processMail() {
6 try {
7 Session session = getMailSession();
8 Store store = connect(session);
9 Folder folder = openMailFolder(store);
10 findContent(folder);
11 } catch (MessagingException e) {
12 throw new RuntimeException(e);
13 } catch (IOException e) {
14 throw new RuntimeException(e);
15 }
16
17 }
18
19 public Session getMailSession() {
20 Properties props = System.getProperties();
21 props.setProperty("mail.store.protocol", "imaps");
22 props.setProperty("mail.imap.partialfetch", "0");
23
24 log.debug("Getting session");
25 return Session.getDefaultInstance(props, null);
26
27 }
28
29 public Store connect(Session session) throws MessagingException {
30 log.debug("getting the session for accessing email.");
31 Store store = session.getStore("imap");
32
33 store.connect("mockserver.com", "testuser", "somepassword");
34 log.debug("Connection established with IMAP server.");
35 return store;
36 }
37
38 public Folder openMailFolder(Store store) throws MessagingException {
39 Folder folder = store.getDefaultFolder();
40 folder = folder.getFolder("inbox");
41 folder.open(Folder.READ_ONLY);
42 return folder;
43 }
44
45 public void findContent(Folder folder) throws MessagingException, IOException {
46 for (Message m : folder.getMessages()) {
47 log.debug(m.getSubject());
48
49 }
50
51
52 }
53
54
55 }
Output is:
DEBUG 30 Aug 2011 19:25:25 SomeImapClient:32 - Getting sessionDEBUG 30 Aug 2011 19:25:25 SomeImapClient:38 - getting the session for accessing email.DEBUG 30 Aug 2011 19:25:25 SomeImapClient:42 - Connection established with IMAP server.DEBUG 30 Aug 2011 19:25:25 SomeImapClient:55 - Some Subject
Some small gotchas:
- your store.connect("example.com", "username", "anything") must match your "username@example.com" addressee in msg.setRecipients; different addressees will yield multiple mailboxes.
- Only works for plain imap & pop3 mailboxes. Even though it doesn't make a lot of sense to use SSL on a mock mailbox, if you try getting the "imaps" store you'll get an error as a real implementation of javamail will be employed.
- I'd always advise to use such tearDown() when doing unit tests, since the Session seems global and different tests could interfere with different contents - unless you use a different fake user/test server url in each of your tests.