如何測試@Async異步任務

spring3支持@Async註解的異步任務,之前大家都是通過使用如線程池來完成,spring3也是使用這種方式,但更簡單。

 

其具體實現在:org.springframework.aop.interceptor.AsyncExecutionInterceptor,是一個方法攔截器,其invoke方法的部分代碼如下: 

Future<?> result = determineAsyncExecutor(specificMethod).submit(
                new Callable<Object>() {
                    public Object call() throws Exception {
                        try {
                            
                            Object result = invocation.proceed();
                            if (result instanceof Future) {
                                return ((Future<?>) result).get();
                            }
                        }
                        catch (Throwable ex) {
                            ReflectionUtils.rethrowException(ex);
                        }
                        return null;
                    }
                });

即把當前任務的調用提交給線程池,很簡單。

 

 

1、測試無事務的異步任務

這個相對來說比較簡單:

1.1、設置任務的返回值爲Future: 

public Future sendSystemMessage(Long[] receiverIds, Message message);

 

1.2、調用future.get();等待任務結束。 

        Future future = messageApi.sendSystemMessage(userIds, message);
        future.get();

 

 這個很簡單。

 

2、測試帶事務的異步任務

因爲是帶事務的,所以異步任務肯定要啓動一個線程來執行任務,所以無法在主線程回滾,造成數據會commit到數據庫,這在集成測試時肯定是不行的;解決方案是移除異步任務:

 

2.1、使用spring profile,在測試環境下不執行<task:annotation-driven>即可。

 

2.2、使用我提供的工具類,在測試時移除異步支持即可: 

        //移除異步支持
        if(AopProxyUtils.isAsync(messageApi)) {
            AopProxyUtils.removeAsync(messageApi);
        }

 

測試類可以參考MessageApiServiceIT.java 

工具類下載 AopProxyUtils.java

 

3、包級別測試 

@Async
public void sendSystemMessage() {
      sendSystemMessageInner();
}

void sendSystemMessageInner() {
      //測試時測試這個方法即可
}

 這樣測試時測試這個包級別的sendSystemMessageInner方法即可

 

 

 其實更好的做法是spring內部提供支持,支持這樣異步調用的測試。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章