2016-05-31 4 views
0

私はcountdownlatchを使っている以下のコードのUnit Testを行う必要があります。これはテストコードのみです。私は、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のような並行処理自体を扱っていません。それは新しいスレッドで実行された場合気にしない、ちょうどあなたの場合に起こる。したがって、このクラスを個別にテストすることができます。コードをうまく構成すると、スレッドの編成を扱うクラスと、他に何も実行しないクラスがあります。アルゴリズムのテストとスレッドの処理のテストを分けやすく、テストを読みやすくしました。
関連する問題