首页 > 解决方案 > 如何在@Async 方法中测试异常?

问题描述

如何断言某个@Async方法内部引发了某个异常?因为 Springs 捕获了以下异常SimpleAsyncUncaughtExceptionHandler

@Service
public class Service {
      @Async
      public void run() {
           throw new RuntimeException();
      }
}

public class Test {
   @Test
   public void test() {
        assertDoesNotThrow(() -> service.run()); //this always passes
   }
}

标签: javaspringspring-bootspring-async

解决方案


如果您的情况可能,请单独测试异步性和实际工作单元。例如,编写将执行的测试(没有“异步”功能)Service.run() 并断言没有/任何/某些异常被抛出。在第二个测试(使用@Async 执行)中,您可以测试实际的工作单元,即使用您的 Spring 提供的 bean 并测试例如:

Awaitility.await().atMost(1000, TimeUnit.MILLISECONDS).untilAsserted(() -> runAnyCodeThatChecksTheResultOfYourServiceRunMethod());

另一种方法可能是将 Service.run() 方法的返回类型替换为 java.util.concurrent.Future,然后 Spring 将重新抛出异常。来自 AsyncExecutionAspectSupport.handleError javadoc:

“如果方法的返回类型是 {@link Future} 对象(同样,如果适用),则可以通过将其抛出到更高级别来传播原始异常。但是,对于所有其他情况,异常不会传回给客户。”


推荐阅读