views:

44

answers:

3

Part of my application depends on JavaMail, moving arranging messages etc. Is it possible to test this module without firing a IMAP server to run the tests on? I am always stuck when it comes to testing stuff that depends on external servers or modules.

+1  A: 

Try using this mock for your test

Chuk Lee
+1  A: 

What you can't test without an IMAP server is, if your application sends an email. But all other things you can if you design your code properly. What you should do is seperate your dependency. What does this mean?

Your code should access the third party code (JavaMail in this case) at only one place (most of the times == only one class). Seperate this class with an interface from the rest of the code, such that you can use an dummy object in your tests.

Here's an example what you should NOT do (assuming JavaMail is the external dependency) :

class Application {
    public run(String[] receiverList, String message, String body) {
        for (String receiver : receiverList) {
           JavaMail.sendMessage(receiver, message, body);
        }
    }
}

You can't test the for loop in this case. Do this instead:

class Application {
    private IApplicatioNMail mail;

    public Application(IApplicationMail mail) {
        this.mail = mail;
    }

    public run(String[] receiverList, String message, String body) {
        for (String receiver : receiverList) {
           mail.sendMessage(receiver, message, body);
        }
    }
}

class JavaApplicationMail implement IApplicationMail {
    public sendMessage(String receiver, String message, String body) {
        JavaMail.sendMessage(receiver, message, body);
    }
}

This way you can create a dummy (mock, whatever) in your tests to replace the JavaApplicationMail. In your tests the external receource is never called).

A test might look something like that:

@Test
public void sentThreeMails() throws Exception {
    IApplicationMail mailCounter = new MailCounter();
    Application application = new Application(mailCounter);
    application.run(new String[] { "one", "two", "three" }, "Hello", "Blah!");

    assertEquals(3, mailCounter.calls);
}

class MailCounter implements IApplicationMail {
    public counter = 0;

    public sendMessage(String receiver, String message, String body) {
        counter++;
    }
}
Arne
+1  A: 

Starting up an IMAP server for your test suite might actually be a good idea. GreenMail was designed for this very purpose, it lets you run in-memory IMAP/POP3/SMTP servers from Java code.

Martin