测试Spring的@Async void返回方法

我在我的Spring应用程序中返回void (或Unit ,我正在写Kotlin)的@Async方法有点问题。

我不知道为什么,但是当@Async方法返回void它只是不执行,或者至少它不会做它应该的。 需要说的是,在我的异步方法中,我想用JavaMailSender发送一封邮件,所以没什么大不了的。 这里是方法:

 @Async override fun sendEmail(locale: Locale, subject: String, message: String, to: String) { val msg = sender.createMimeMessage() println("1") val helper = MimeMessageHelper(msg, true, "utf-8") helper.setFrom("email@example.com") helper.setTo(to) println("2") helper.setSubject(getSubject(locale, null)) println("3") helper.setText(processTemplate(locale, null, null), true) println("4") sender.send(msg) println("5") } 

但电子邮件永远不会来,没有异常记录(我正在运行testNG测试)。

当我改变函数的签名使其返回Future<String>并在函数的末尾添加一些虚拟的返回行,然后调用service.sendEmail(...).get() ,方法的主体以奇迹般的方式执行和电子邮件到达。

在我的@Configuration类中,有@EnableAsync 。 我还实现了AsyncConfigurer并提供了自己的执行程序和异常处理程序,因为我认为它可能是我的执行程序bean定义的东西,但没有任何帮助。

这让我疯狂,因为我只是想在后台默默地执行一些东西,而且不起作用。 我默默地说,我不想被内部抛出的异常所困扰。

你有什么想法吗?

更新:所以建议@pleft,我在我的方法中打印一些打印。 现在,当我运行mvn clean test ,我可以看到1,2,3是打印的, 但是不是每一次。 有时只有1和2打印。 我也把打印在我的AsyncUncaughtExceptionHandler ,但那个不被调用。 它看起来像后台线程被杀太快或什么的。

更新2:

我的服务配置:

 @Configuration @EnableScheduling @EnableAsync @ComponentScan class ServiceConfig : ApplicationContextAware, EnvironmentAware, AsyncConfigurer { override fun getAsyncUncaughtExceptionHandler(): AsyncUncaughtExceptionHandler { return AsyncUncaughtExceptionHandler { ex, method, params -> println("Exception thrown") } } override fun getAsyncExecutor(): Executor { val executor = ThreadPoolTaskExecutor() executor.corePoolSize = 2 executor.maxPoolSize = 2 executor.setQueueCapacity(500) executor.threadNamePrefix = "asyncThread" executor.initialize() return executor } } /// other beans definitions.. 

也许这很重要,也许不是,但是我正在使用Thymeleaf的ProcessTemplate方法。

根据评论中的对话和我自己的观察(就像在测试方法中进行一些睡眠),我找到了原因。 这是测试中破坏了Spring Context的原因。 因为我只有一个测试运行这个异步方法,所以情况是async方法立即返回,测试方法也是如此。 因为它是我测试套件中的最后一个(也是唯一的)方法,所以测试上下文被销毁(以及它所创建的所有线程)。

所以决议是要么睡觉在测试(非常丑陋)或看看这个问题,并得到启发。