所以我有一個方法啓動五個線程。我想編寫一個單元測試來檢查五個線程是否已經啓動。我怎麼做?示例代碼非常感謝。Junit測試正確的線程數已經開始
回答
而不是編寫自己的方法來啓動線程,爲什麼不使用Executor
,它可以注入你的課堂?然後,您可以通過傳入虛擬Executor
來輕鬆測試它。
編輯:這裏是你的代碼是如何可以構造一個簡單的例子:
public class ResultCalculator {
private final ExecutorService pool;
private final List<Future<Integer>> pendingResults;
public ResultCalculator(ExecutorService pool) {
this.pool = pool;
this.pendingResults = new ArrayList<Future<Integer>>();
}
public void startComputation() {
for (int i = 0; i < 5; i++) {
Future<Integer> future = pool.submit(new Robot(i));
pendingResults.add(future);
}
}
public int getFinalResult() throws ExecutionException {
int total = 0;
for (Future<Integer> robotResult : pendingResults) {
total += robotResult.get();
}
return total;
}
}
public class Robot implements Callable<Integer> {
private final int input;
public Robot(int input) {
this.input = input;
}
@Override
public Integer call() {
// Some very long calculation
Thread.sleep(10000);
return input * input;
}
}
下面是你如何把它從你的main()
:
public static void main(String args) throws Exception {
// Note that the number of threads is now specified here
ExecutorService pool = Executors.newFixedThreadPool(5);
ResultCalculator calc = new ResultCalculator(pool);
try {
calc.startComputation();
// Maybe do something while we're waiting
System.out.printf("Result is: %d\n", calc.getFinalResult());
} finally {
pool.shutdownNow();
}
}
這裏是你如何'd測試它(假設JUnit 4和Mockito):
@Test
@SuppressWarnings("unchecked")
public void testStartComputationAddsRobotsToQueue() {
ExecutorService pool = mock(ExecutorService.class);
Future<Integer> future = mock(Future.class);
when(pool.submit(any(Callable.class)).thenReturn(future);
ResultCalculator calc = new ResultCalculator(pool);
calc.startComputation();
verify(pool, times(5)).submit(any(Callable.class));
}
請注意,所有這些代碼只是一個草圖,我還沒有測試甚至試圖編譯。但它應該讓你瞭解代碼的結構。
而不是說你要「測試五個線程已經開始」,最好退一步考慮五線程實際上應該是什麼做。然後進行測試以確保「某事」實際上正在完成。
如果你真的只想測試線程已經啓動,那麼你可以做一些事情。你是否保持對某個地方的線程的引用?如果是這樣,您可以檢索參考文獻,對它們進行計數,並在每個參考文獻上撥打isAlive()
(檢查它是否返回true
)。
我相信在某些Java平臺類中有一些方法,您可以調用它來查找有多少個線程正在運行,或查找所有在ThreadGroup
中運行的線程,但是您必須搜索以找出它是。
更多的想法響應您的評論
如果你的代碼是new Thread(runnable).start()
一樣簡單,我不會刻意去測試該線程實際上是開始。如果你這樣做,你基本上只是測試Java平臺的工作原理(它的確如此)。如果你初始化和啓動線程的代碼比較複雜,我會把thread.start()
部分取出來,並確保這個存根被稱爲所需的次數,並帶有正確的參數等。
無論你做什麼關於這一點,我會絕對測試在多線程模式下運行時任務是否正確完成。從個人經驗,我可以告訴你儘快當你開始做什麼遠程複雜的線程,它很容易得到微妙的錯誤,只有在某些條件下,也許只是偶爾出現。處理多線程代碼的複雜性是一個非常滑的斜坡。因此,如果你能做到這一點,我會高度建議你不僅僅是簡單的單元測試。在多核線程上,多核機器上,非常大的數據集上執行壓力測試,並確保所有答案都與預期完全一致。
此外,雖然您期待使用線程的性能提升,但我建議您使用不同數量的線程來測試您的程序,以確保達到預期的性能提升。根據您的系統設計方式,可能會發現併發瓶頸,這可能會使您的程序在線程中的速度難於沒有線程。在某些情況下,它甚至可以是較慢的!
- 1. JUnit線程測試
- 2. SurfaceView和線程已經開始異常
- 3. 使用Junit測試線程
- 4. JUnit,測試和線程
- 5. 從JUnit測試確認FileReader已正確關閉
- 6. Java線程錯誤IllegalThreadState線程已經開始
- 7. 交錯並行測試在junit開始?
- 8. Junit 3,從java方法開始測試
- 9. 測試最近啓動的活動是否已經開始
- 10. this.subject()在測試開始時返回已經銷燬的對象
- 11. Session已經開始
- 12. 如何正確編寫JUnit測試?
- 13. 正確定義jUnit測試用例
- 14. 證明更高的管理,測試已經正確完成
- 15. Junit已經有try-catch子句的方法的測試用例
- 16. SpringBoot junit測試多個TomcatServletContainerInitializer的 - BindException:地址已經在使用「
- 17. 確保所有線程後的C#集成測試已經停止
- 18. Hibernate + JUnit多線程集成測試
- 19. JUnit測試:如何測試線程的結果
- 20. JUnit測試用例中的線程測試SharedResource類
- 21. 測試imageview已經正確設置了uri
- 22. 獲取線程已經開始此類錯誤?
- 23. 將變量傳遞到線程後,它已經開始
- 24. 有線JUnit測試斷言
- 25. 當已經在正確的線程中Form.Invoke呢?
- 26. 多線程問題+ DataReady已經打開
- 27. 還沒開始線程但Python拋出異常'線程已經啓動'
- 28. JUnit測試(正面和負面測試)
- 29. Junit測試以測試原始數據類型
- 30. 參數JUnit測試
請參閱我對@Alex D的迴應。你能舉個例子嗎? – kasavbere 2012-07-25 06:40:04
@kasavbere請參閱提供幾個示例的[ExecutorService的javadoc](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/ExecutorService.html)。 – assylias 2012-07-25 09:14:37
感謝這個例子。 – kasavbere 2012-07-30 00:51:49