2013-03-02 19 views
6

ユニットテストはデバッグモードで成功しますが、正常に実行されないのはなぜですか? ExecutorServiceの中の1 -ユニットテストはデバッグモードで成功しますが、正常に実行すると失敗します

public class ExecutorServiceTest extends MockitoTestCase{ 
    private int numThreads; 
    private ExecutorService pool; 
    private volatile boolean interruptedBitSet; 

    @Override 
    public void setUp() { 
    numThreads = 5; 
    pool = Executors.newFixedThreadPool(numThreads); 
    } 

class TaskChecksForInterruptedBit implements Callable<String> { 
    @Override 
    public String call() throws Exception { 
     interruptedBitSet = false; 
     while (!Thread.currentThread().isInterrupted()) { 
     } 
     interruptedBitSet = Thread.currentThread().isInterrupted(); 
     return "blah"; 
    } 
    } 

public void testCancelSetsInterruptedBitInCallable() throws Exception { 
    interruptedBitSet = false; 
    final Future<String> future = 
     pool.submit(new TaskChecksForInterruptedBit()); 
    final boolean wasJustCancelled = future.cancel(true); 
    assertTrue(wasJustCancelled); 

    // Give time for the thread to notice the interrupted bit and set the flag 
    Thread.sleep(5000); 

    // This succeeds when stepping through w/ a debugger, but fails when running 
    // the test straight. WHY? 
    assertTrue(interruptedBitSet); 

    assertTrue(future.isDone()); 
    assertTrue(future.isCancelled()); 
    } 
} 
+1

提案、 'interruptedBitSet'を' volatile'にしてみてください – yohlulz

+0

これは動作しませんでした。 –

+0

デバッグ時のブレークポイントはどこですか? – Alb

答えて

1

タスクが実際に実行されていることを確認する必要があります。チャンスがある前にキャンセルされることがあります。

public class ExecutorServiceTest { 
    private int numThreads; 
    private ExecutorService pool; 
    private volatile boolean interruptedBitSet; 
    private static final CountDownLatch latch = new CountDownLatch(1); 

    @Before 
    public void setUp() { 
     numThreads = 5; 
     pool = Executors.newFixedThreadPool(numThreads); 
    } 

    class TaskChecksForInterruptedBit implements Callable<String> { 
     @Override 
     public String call() throws Exception { 
      interruptedBitSet = false; 
      latch.countDown(); 
      while (!Thread.currentThread().isInterrupted()) { 
       System.out.println(System.currentTimeMillis()); 
      } 
      System.out.println("haha"); 
      interruptedBitSet = Thread.currentThread().isInterrupted(); 
      return "blah"; 
     } 
    } 

    @Test 
    public void testCancelSetsInterruptedBitInCallable() throws Exception { 
     final Future<String> future = 
       pool.submit(new TaskChecksForInterruptedBit()); 
     interruptedBitSet = false; 
     latch.await(); 
     final boolean wasJustCancelled = future.cancel(true); 
     Assert.assertTrue(wasJustCancelled); 

     // Give time for the thread to notice the interrupted bit and set the flag 
     Thread.sleep(5000); 

     // This succeeds when stepping through w/ a debugger, but fails when running 
     // the test straight. WHY? 
     Assert.assertTrue(interruptedBitSet); 

     Assert.assertTrue(future.isDone()); 
     Assert.assertTrue(future.isCancelled()); 
    } 
} 
3

理由は、デバッガでブレークポイントは、バックグラウンドスレッドのいずれかのメインスレッドを停止したがされていないことはほぼ確実です。 Eclipseでデバッグするときは、メインスレッドではなくすべてのスレッドを停止するようにブレークポイントを変更することができます。

タスクの提出をデバッグせず、即時取り消しが速すぎると、一度実行する前にタスクを取り消すことができます。

final Future<String> future = pool.submit(new TaskChecksForInterruptedBit()); 
Thread.sleep(1000); 
final boolean wasJustCancelled = future.cancel(true); 
+0

メインスレッドは、リリースモードで変更されたフラグ(生成されたスレッドによって変更されたもの)が表示されないのはなぜですか? –

+0

私にはっきりさせておきます:私はcallableのcall()メソッドではなく、テストメソッドで'interruptedBitSet = false 'に設定しました。 –

+0

@ Chris-Morris申し訳ありませんが、最初にコードを誤読しました。別の提案で自分の回答を編集しました – Alb

1

私はこれが古いと知っていますが、同じ問題がありました。 私の問題は、私がIEnumerableを持っていて、出力を列挙してチェックしていたということでした。

ユニットテストを実行しているときに、IEnumerableが、デバッグ時と異なる順序を返していました。これはIEnumerableの性質であり、単にOrderBy節を追加すると私の問題が解決しました。

これは、見つけにくい問題である可能性があるため、これが誰かを助けてくれることを願っています。

0

あなたは、すべてのスレッドがオンラインコースからの宿題を実行している間、私は同様の問題を抱えていたメインスレッド

private void shutdownExecutionService(ExecutorService executorService) { 
    if (executorService != null) { 
     try { 
      executorService.shutdown(); 
      while (!executorService.awaitTermination(10, TimeUnit.HOURS)) { 
       logger.info("Awaiting completion of threads."); 
      } 
     } catch (final InterruptedException e) { 
      logger.error("Error while shutting down threadpool", e); 
     } 
    } 
} 
0

を終了する前に死ぬかどうかを確認する必要があります。私がビルドパスに追加したコースのグレーダープログラムは、JUnit4を使用しました。私のバージョンのEclipseは、新しいテストケースにJUnit5を追加しました。私は新しいJavaプロジェクトを作成し、テストケースのビルドバスにJUnit5を追加しました。お役に立てれば。

関連する問題