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

发布于 2024-10-06 18:07:26 字数 1179 浏览 6 评论 0原文

我有几个邮件程序,我很想在它们上使用 @Async 并获得异步邮件的好处。

我遇到的唯一问题是我不知道如何正确测试它们,并且我想轻松地采用我当前测试它们的方法,只需修改它而不对测试代码进行大量更改,如果这是可能的。

例如,在测试类中,我将定义两个自动装配的 bean。一个是邮件服务,它负责执行所有类似邮件的事务,另一个是 JavaMailSender - 但它是一个模拟。然后,我将模拟放入服务中,这样它实际上不会发送真正的电子邮件;)

@Autowired
Mailer mailer;

MockJavaMailSender mailSender;

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

这种方法效果非常好,因为我可以问我的模拟问题或从中获取数据以确保我的邮件程序代码有效:

UserAccount userAccount = userAccountDao.find(1);

mailer.sendRetrievePassword(userAccount);

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

// Do tests on text.

@Async 的问题是 mailSender 尚未填充,因此测试将失败。

这是使用 @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));
}

有没有一种非常简单的方法来纠正这个问题?

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?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

审判长 2024-10-13 18:07:26

嗯,看来这可能是解决方案。我真的不想返回 mime 消息,因为我的应用程序不需要...但它有效:

@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);
}

下面是使其通过的测试:

@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);
}

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);
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文