Контекст
У меня есть:
- очень простой метод для асинхронного запуска:
Код: Выделить всё
@Async public void asyncMethod() { System.out.println("entering method..."); try { Thread.sleep(10000); } catch (InterruptedException e) { throw new RuntimeException(e); } System.out.println("exiting method..."); } - Служба Executor, объявленная в @Configuration, которая использует @EnableAsync
Код: Выделить всё
@Configuration @EnableAsync public class AsyncConfig implements AsyncConfigurer { @Override public Executor getAsyncExecutor() { ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor(); executor.setCorePoolSize(5); executor.setMaxPoolSize(10); executor.setQueueCapacity(100); executor.setThreadNamePrefix("myAsyncStuff-"); executor.initialize(); return executor; } } - Затем асинхронный метод активируется из конечной точки @RestController [не разделяет содержимое контроллера, поскольку это вряд ли имеет значение]
- Наконец, я вызываю конечную точку контроллера из теста JUnit, интегрированного в полный контекст приложения с помощью @SpringBootTest
Код: Выделить всё
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE, useMainMethod = SpringBootTest.UseMainMethod.ALWAYS) public class SomeIntegrationTest { @Autowired MockMvc mockMvc; @Autowired ThreadPoolTaskExecutor taskExecutor; @Test void someTest() throws Exception { final var body = """ {"someKey": "someValue"} """; mockMvc.perform(post("/api/myEndpoint") .accept(MediaType.APPLICATION_JSON_VALUE) .contentType(MediaType.APPLICATION_JSON_VALUE) .content(body)) .andExpect(status().isOk()); taskExecutor.setWaitForTasksToCompleteOnShutdown(true); // ensuring that the taskExecutor awaits completion taskExecutor.shutdown(); // call to shutdown final var asyncFinished = taskExecutor.getThreadPoolExecutor().awaitTermination(5, TimeUnit.MINUTES); // await doing nothing !!! Assertions.assertTrue(asyncFinished); } }
Простой метод @Async, правильно интегрированный в соответствии с официальной документацией, вызывается, пул закрывается, но awaitTermination ничего не делает, и поток прерывается до того, как метод достигнет конца.
В журналах на консоли для someTest отображается только результат первого println:
Код: Выделить всё
> entering method...
Подробнее здесь: https://stackoverflow.com/questions/798 ... completion
Мобильная версия