Java 如何在@Async void方法中断言异常?
我想断言应该在Java 如何在@Async void方法中断言异常?,java,spring,spring-boot,spring-boot-test,spring-async,Java,Spring,Spring Boot,Spring Boot Test,Spring Async,我想断言应该在@Asyncvoid方法中引发的异常 以下操作失败,即使我已经添加了一个SyncTaskExecutorexplicit org.opentest4j.AssertionFailedError:预期将引发RuntimeException,但未引发任何内容 由于@Async方法由来自asyncExecutor的线程异步执行,并且由于RuntimeException而终止,这对主线程没有任何影响,因此实际上Main Test线程在触发异步调用后成功地与流的其余部分竞争一次。因此,我建议
@Async
void方法中引发的异常
以下操作失败,即使我已经添加了一个SyncTaskExecutor
explicit
org.opentest4j.AssertionFailedError:预期将引发RuntimeException,但未引发任何内容
由于
@Async
方法由来自asyncExecutor
的线程异步执行,并且由于RuntimeException
而终止,这对主线程没有任何影响,因此实际上Main Test
线程在触发异步调用后成功地与流的其余部分竞争一次。因此,我建议使用,始终保持异步进程的引用,即使它是必需的或不需要的,并且在测试用例中确实会有所帮助
@Service
@Async
public class AsyncService {
public CompletableFuture<Void> run() {
//of course real world is more complex with multiple sub calls here
throw new RuntimeException("junit test");
}
}
关于断言包装异常,您还可以参考另一个注意事项,因为
@Async
方法由asynceducer
中的线程异步执行,并且由于RuntimeException
而终止,这对主线程没有任何影响,实际上,Main测试
线程触发异步调用后,会与流的其余部分成功竞争一次。因此,我建议使用,始终保持异步进程的引用,即使它是必需的或不需要的,并且在测试用例中确实会有所帮助
@Service
@Async
public class AsyncService {
public CompletableFuture<Void> run() {
//of course real world is more complex with multiple sub calls here
throw new RuntimeException("junit test");
}
}
关于断言包装异常,您还可以参考另一个注意事项如何使用将为您的应用程序定义的异常
所以,基本上,当您执行抛出异常的方法时,您可以验证异常是在处理程序中处理的吗?只是一个想法,没有尝试过。如何使用将为您的应用程序定义的工具
所以,基本上,当您执行抛出异常的方法时,您可以验证异常是在处理程序中处理的吗?只是一个想法,我没有尝试过。我面临着同样的问题 bilak的帖子提出了让我的自定义
AsyncUncaughtExceptionHandler
声明一个@组件
注释的想法。
然后,在我的AsyncConfigurer
自定义实现中,我注入了我的自定义AsyncUncaughtExceptionHandler
在测试中,我在自定义的AsyncUncaughtExceptionHandler
上使用了@MockBean
注释,因此我能够验证调用handleUncaughtException
时是否存在适当的异常
代码示例:
AsyncExceptionHandler
@Slf4j
@Component
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
log.error("Exception while executing with message: {} ", throwable.getMessage());
log.error("Exception happen in {} method ", method.getName());
}
}
自定义异步配置器
@Configuration
public class CustomAsyncConfigurer implements AsyncConfigurer {
final private AsyncExceptionHandler asyncExceptionHandler;
@Autowired
public TaskExecutorConfiguration(AsyncExceptionHandler asyncExceptionHandler) {
this.asyncExceptionHandler = asyncExceptionHandler;
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(50);
executor.setThreadNamePrefix("AsyncThread::");
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return asyncExceptionHandler;
}
}
我的单元测试:
class FooServiceTest extends FooApplicationTests {
@MockBean
private AsyncExceptionHandler asyncExceptionHandler;
@Autowired
private FooService fooService;
@Test
void testCreateEnrollmentBioStoreException() throws Exception {
fooService.doBar();
ArgumentCaptor<FooException> argumentCaptor = ArgumentCaptor.forClass(FooException.class);
verify(asyncExceptionHandler, times(1)).handleUncaughtException(argumentCaptor.capture(), any(), any());
FooException exception = argumentCaptor.getValue();
assertEquals("Foo error message", exception.getMessage());
}
}
class FooServiceTest扩展了FooApplicationTests{
@蚕豆
私有AsyncExceptionHandler AsyncExceptionHandler;
@自动连线
私人餐饮服务;
@试验
void testCreateEnrollmentBioStoreException()引发异常{
fooService.doBar();
ArgumentCaptor ArgumentCaptor=ArgumentCaptor.forClass(FooException.class);
验证(asyncExceptionHandler,次(1)).handleUncaughtException(argumentCaptor.capture(),any(),any());
FooException=argumentCaptor.getValue();
assertEquals(“Foo错误消息”,exception.getMessage());
}
}
我不确定这是不是正确的方法,但我有一个void方法被转换成了async,所以我不想仅仅为了测试而更改返回值。我也面临同样的问题 bilak的帖子提出了让我的自定义
AsyncUncaughtExceptionHandler
声明一个@组件
注释的想法。
然后,在我的AsyncConfigurer
自定义实现中,我注入了我的自定义AsyncUncaughtExceptionHandler
在测试中,我在自定义的AsyncUncaughtExceptionHandler
上使用了@MockBean
注释,因此我能够验证调用handleUncaughtException
时是否存在适当的异常
代码示例:
AsyncExceptionHandler
@Slf4j
@Component
public class AsyncExceptionHandler implements AsyncUncaughtExceptionHandler {
@Override
public void handleUncaughtException(Throwable throwable, Method method, Object... objects) {
log.error("Exception while executing with message: {} ", throwable.getMessage());
log.error("Exception happen in {} method ", method.getName());
}
}
自定义异步配置器
@Configuration
public class CustomAsyncConfigurer implements AsyncConfigurer {
final private AsyncExceptionHandler asyncExceptionHandler;
@Autowired
public TaskExecutorConfiguration(AsyncExceptionHandler asyncExceptionHandler) {
this.asyncExceptionHandler = asyncExceptionHandler;
}
@Override
public Executor getAsyncExecutor() {
ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
executor.setCorePoolSize(10);
executor.setMaxPoolSize(20);
executor.setQueueCapacity(50);
executor.setThreadNamePrefix("AsyncThread::");
executor.initialize();
return executor;
}
@Override
public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
return asyncExceptionHandler;
}
}
我的单元测试:
class FooServiceTest extends FooApplicationTests {
@MockBean
private AsyncExceptionHandler asyncExceptionHandler;
@Autowired
private FooService fooService;
@Test
void testCreateEnrollmentBioStoreException() throws Exception {
fooService.doBar();
ArgumentCaptor<FooException> argumentCaptor = ArgumentCaptor.forClass(FooException.class);
verify(asyncExceptionHandler, times(1)).handleUncaughtException(argumentCaptor.capture(), any(), any());
FooException exception = argumentCaptor.getValue();
assertEquals("Foo error message", exception.getMessage());
}
}
class FooServiceTest扩展了FooApplicationTests{
@蚕豆
私有AsyncExceptionHandler AsyncExceptionHandler;
@自动连线
私人餐饮服务;
@试验
void testCreateEnrollmentBioStoreException()引发异常{
fooService.doBar();
ArgumentCaptor ArgumentCaptor=ArgumentCaptor.forClass(FooException.class);
验证(asyncExceptionHandler,次(1)).handleUncaughtException(argumentCaptor.capture(),any(),any());
FooException=argumentCaptor.getValue();
assertEquals(“Foo错误消息”,exception.getMessage());
}
}
我不确定这是不是正确的方法,但我有一个void方法被转换为async,所以我不想仅仅为了测试而更改返回值。这个方法完全失败。因为在junit测试中,
@Async
void方法仍然执行Async,即使提供了SyncTaskExecutor
。所以,我仍然想测试这个异常……使用这个方法它完全失败了。因为在junit测试中,@Async
void方法仍然执行Async,即使提供了SyncTaskExecutor
。所以,我仍然想测试异常…但这需要更改应用程序代码,并使用返回值,仅用于测试,而无需实际使用。但我始终更喜欢保留子作业引用,而不是将其单独保留,因为这可能适用于web应用程序,但在正常的java世界中,子线程可能会在父线程终止时立即终止,但我认为你可以等待更好的答案@membersoundWell,但这需要更改带有返回值的应用程序代码,仅用于测试,而无需实际使用。但我始终更喜欢keep child作业引用,而不是将其单独保留,因为这可能在web应用程序中有效,但在普通java世界中,子线程可能会在父线程终止时立即终止,但我认为您可以等待bett