Reputation: 86925
How can I assert that a certain exception is thrown inside an @Async
method?
Because the following exception is caught by 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
}
}
Upvotes: 3
Views: 1417
Reputation: 3167
import static org.awaitility.Awaitility.await;
Awaitility.await().atMost(5, TimeUnit.SECONDS)
.untilAsserted(() -> assertThrows(RuntimeException.class, () -> service.run()));
Upvotes: -1
Reputation: 688
If it is possible for your case, separate testing of asynchronicity and the actual unit of work. E.g. write test that will execute (no 'Async' functionality) Service.run() and assert that no/any/some exceptions are thrown. In second test (utilizing @Async execution) you could test for the actual unit of work i.e. use your Spring provided bean and test for e.g.:
Awaitility.await().atMost(1000, TimeUnit.MILLISECONDS).untilAsserted(() -> runAnyCodeThatChecksTheResultOfYourServiceRunMethod());
Another method might be to replace the return type of the Service.run() method to java.util.concurrent.Future, Spring will then re-throw the exception. From AsyncExecutionAspectSupport.handleError javadoc:
"If the return type of the method is a {@link Future} object (again, if applicable), the original exception can be propagated by just throwing it at the higher level. However, for all other cases, the exception will not be transmitted back to the client."
Upvotes: -1