[英]How to get ExecutorService or CompletionService to finish without asking for values of Futures?
我們需要在一個線程中完成一些工作,該線程將使用Spring Boot在Web應用程序的服務器上運行。
我們想要發生的是:1)工作作為我們的自定義Runnable對象提交2)工作輪到它完成時(它是數據庫操作,並且不需要任何返回值,除非運行即可返回“成功” ()已完成,無例外)
但是,在我們的JUnit測試中,似乎主線程完成后,提交給ExecutorService或CompletionService的所有任務都會消失,除非每次添加新任務時都調用take()(因為它阻塞直到任務完成,所以這使任務按順序運行(這會違背目的)),或者如果我們維護期貨列表並調用一種方法來遍歷列表並獲取每個功能的值的方法。
我們認為后一種選擇不是理想的選擇,因為作為服務器應用程序,我們將不斷收到來自不同用戶的請求,並且不知道如何檢測何時應該清除期貨清單。
為什么線程會靜默消失,如何解決呢?
不要異步運行代碼:只需直接測試Runnable
:
@Test
public void test() {
Runnable r = <your runnable>;
r.run();
// various assertions
}
您選擇的ExecutorService
完成其工作是毫無意義的測試-您可以假設這樣做。
如果您想斷言您的應用程序行為正確,請使用功能測試; 即,使用超音速數據源啟動一個容器(例如,使用@SpringJUnit4ClassRunner
),擊中spring boot的端點,然后使您斷言對數據庫的影響。
如果您對服務使用spring boot的@Async
批注,則甚至可以提供使用SynchronousTaskExecutor
的配置,因此您不必在斷言之前暫停測試。
測試異步代碼的一種好方法是使用ConcurrentUnit之類的方法阻塞主測試線程並在回調中執行斷言。 這是一個使用CompletableFuture的whenComplete
回調的whenComplete
:
Waiter waiter = new Waiter();
CompletableFuture<Connection> future = someService.connect();
future.whenComplete((connection, failure) -> {
// Called from some other thread
waiter.assertNotNull(connection);
waiter.assertNull(failure);
waiter.resume();
});
// Block the main test thread
waiter.await();
如果回調線程中的任何一個聲明失敗,則測試將按預期失敗。 主測試線程將在完成測試之前等待resume
調用。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.