How to properly test @Async mailers in Spring 3.0.x?

I have several mailers that I'd just love to slap @Async on and reap the benefits of asynchronous mailing.

The only problem I'm having is that I don't know how to properly test them, and I'd like to easily take the method I'm currently testing them with and just modify it without making massive changes to the test code if that's possible.

For example, in a test class, I'll define two autowired beans. One is the mailer service, which is responsible for doing all mail-like transactions, and the other is the JavaMailSender - but it's a mock. I then place the mock into the service so that it doesn't actually send the real emails ;)

@Autowired
Mailer mailer;

MockJavaMailSender mailSender;

@Before
public void setup() {
    mailSender = new MockJavaMailSender();
    mailer.setMailSender(mailSender);
}

This approach has worked out really well, because I can just ask my mock questions or get data from it to make sure my mailer code works:

UserAccount userAccount = userAccountDao.find(1);

mailer.sendRetrievePassword(userAccount);

mailSender.assertTimesSent(1);
String text = mailSender.getMimeMessage().buildText();

// Do tests on text.

The problem with @Async is that mailSender won't be populated yet, so the tests will fail.

here is the code that uses @Async:

@Async
@Override
public void sendRetrievePassword(UserAccount userAccount) {
    mailSender.send(new MimeMessageSupport(velocityEngine)
        .setTitle("Retrieve Password")
        .setTemplate("mail/retrievePassword.vm")
        .setToEmailAddress(userAccount.getEmailAddress())
        .addObject("userAccount", userAccount));
}

Is there a really easy way to correct this?


Well, it seems like this could be the solution. I don't really want to return the mime message as my application doesn't need to... but it works:

@Async
@Override
public Future<MimeMessageSupport> sendRetrievePassword(UserAccount userAccount) {
    MimeMessageSupport mimeMessage = new MimeMessageSupport(velocityEngine)
        .setTitle("Retrieve Password")
        .setTemplate("mail/retrievePassword.vm")
        .setToEmailAddress(userAccount.getEmailAddress())
        .addObject("userAccount", userAccount);

    mailSender.send(mimeMessage);

    return new AsyncResult<MimeMessageSupport>(mimeMessage);
}

And here's the test to make it pass:

@Test
public void sendRetrievePassword() throws ExecutionException, InterruptedException {
    UserAccount userAccount = userAccountDao.find(1);

    Future<MimeMessageSupport> future = mailer.sendRetrievePassword(userAccount);

    String text = future.get().buildText();

    assertTrue(text.contains(userAccount.getEmailAddress()));
    assertTrue(text.contains(userAccount.getPassword()));

    mailSender.assertTimesSent(1);
}
链接地址: http://www.djcxy.com/p/93488.html

上一篇: 如何针对不同的测试使用不同的数据源

下一篇: 如何在Spring 3.0.x中正确测试@Async邮件程序?