2016-05-31 51 views
0

我需要做下面的代碼使用countdownlatch的單元測試。這只是一個測試代碼。我正在使用mockito thenAnswer和InvocationOnMask來模擬線程/可調用。但我不知道如何在單元測試中初始化/模擬或退出countdownlatch。如何使用CountDownLatch測試一個方法?

public class ThreadPoolTaskExecRunner { 
    private ThreadPoolTaskExecutor threadPoolTaskExecutor = new ThreadPoolTaskExecutor(); 
    private ArrayBlockingQueue<String> values = new ArrayBlockingQueue<String>(100, true); 

    public ThreadPoolTaskExecRunner() { 
     threadPoolTaskExecutor.setCorePoolSize(5); 
     threadPoolTaskExecutor.setMaxPoolSize(10); 
     threadPoolTaskExecutor.setWaitForTasksToCompleteOnShutdown(true); 
     threadPoolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); 
     threadPoolTaskExecutor.initialize(); 
    } 

    public static void main(String args[]) { 
     ThreadPoolTaskExecRunner obj = new ThreadPoolTaskExecRunner(); 
     obj.testCountDownLatch(); 
    } 
    public void testCountDownLatch() { 
     final CountDownLatch latch = new CountDownLatch(5); 
     Future<String> future1 = threadPoolTaskExecutor.submit(new Task("A", values, latch)); 
     Future<String> future3 = threadPoolTaskExecutor.submit(new Task("B", values, latch)); 
     Future<String> future4 = threadPoolTaskExecutor.submit(new Task("C", values, latch)); 
     Future<String> future5 = threadPoolTaskExecutor.submit(new Task("D", values, latch)); 
     Future<String> future2 = threadPoolTaskExecutor.submit(new Task("E", values, latch)); 

     try{ 
      latch.await(); //main thread is waiting on CountDownLatch to finish 
     }catch(InterruptedException ie){ 
      System.out.println(ie); 
     } 
     System.out.println("*********** DONE *********** values size= "+values.size()); 
     for(String s : values) 
      System.out.println(s); 
     threadPoolTaskExecutor.shutdown(); 
    } 

    public static class Task implements Callable<String> { 
     private String type; 
     private ArrayBlockingQueue<String> values; 
     private CountDownLatch latch; 

     public Task(String s, ArrayBlockingQueue<String> values, CountDownLatch latch) { 
      this.type = s; 
      this.values = values; 
      this.latch = latch; 
     } 

     @Override 
     public String call() throws Exception { 
      try { 
       System.out.println("Inside call type: " + type); 
       Thread.sleep(10); 
       values.add(type); 
       return type; 
      } finally { 
       if(latch != null) 
        latch.countDown(); 
      } 
     } 
    } 
} 

我公司開發的單元測試類,但它是沒有幫助的......

@RunWith(MockitoJUnitRunner.class) 
public class ThreadPoolTaskExecRunnerTest { 
    @Mock 
    private ThreadPoolTaskExecutor taskExecutor; 

    @InjectMocks 
    ThreadPoolTaskExecRunner threadPoolTaskExecRunner; 

    @Test 
    public void test() { 
     when(taskExecutor.submit(any(ThreadPoolTaskExecRunner.Task.class))).thenAnswer(new Answer<Future<String>>() { 
      public Future<String> answer(InvocationOnMock invocation) throws Throwable { 
       Future<String> future = mock(FutureTask.class); 
       when(future.isDone()).thenReturn(false, false, true); 
       when(future.get()).thenReturn("This is a test"); 
       return future; 
      } 
     }); 

     threadPoolTaskExecRunner.testCountDownLatch(); 
    } 
} 
+0

你不應該測試你沒寫的代碼......你曾經寫過一個單元測試List/Array/Integer等?此外,你究竟想要測試什麼? – alfasin

+0

看起來像我的方法名稱testCountDownLatch()讓你感到困惑。我的服務需要並行執行一些任務,並且應該等待所有任務完成。我正在使用countdowlatch。現在我需要測試我的服務。請將testCountDownLatch()方法作爲我的服務方法... – ganesh

回答

1

好你要考什麼?我想你想測試countDown被調用。所以,你可以做這樣的:

public void taskCallsCountDownOnce() { 
    // setup 
    final CountDownLatch latch = mock(CountDownLatch.class); 

    // execution 
    new Task("A", values, latch).call(); 

    // evaluation 
    verify(latch).countDown(); 
} 

如果你也想測試值在呼喚倒計時結束之前加入,然後使用:

public void taskAddsValueBeforeCallingCountDown() { 
    // setup & execution 
    // ... 
    // evaluation 
    InOrder inOrder = inOrder(latch, values); 
    inOrder.verify(values).add(...); 
    inOrder.verify(latch).countDown(); 
} 

一般注意事項:

  • 在這種特殊情況下,撥打Future.get()將更容易,這也將等到完成任務
  • 給你的測試方法描述性的名稱,有助於瞭解您正在測試的內容
  • 儘量保持併發性儘量遠離您的單元測試。大多數類並不像自己的類Task那樣處理併發性。它不關心它是否在新線程中執行,它只是在你的情況。所以你可以單獨測試這個類。如果你很好地構建你的代碼,你將會有一些類來處理線程組織,沒有其他的類和其他類來執行工作,而沒有別的。這使得分離算法測試和線程處理測試變得更簡單,而且測試更容易閱讀。
相關問題