13

単体テストがデバッグ モードでは成功するのに、正常に実行すると失敗するのはなぜですか?

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());
  }
}
4

5 に答える 5

3

その理由は、ほぼ確実に、デバッガーのブレークポイントがメイン スレッドを停止しているが、バックグラウンド スレッド (ExecutorService 内のスレッド) を停止していないためです。Eclipse でデバッグする場合、メイン スレッドだけでなくすべてのスレッドを停止するようにブレークポイントを変更できます。

タスクの送信をデバッグしていない場合、および即時のキャンセルは非常に迅速であるため、一度実行する前にタスクをキャンセルしています。これらの行の間にスリープ遅延を追加してみてください:

final Future<String> future =  pool.submit(new TaskChecksForInterruptedBit());
Thread.sleep(1000);
final boolean wasJustCancelled = future.cancel(true);
于 2013-03-02T00:33:44.613 に答える
2

タスクが実際に実行を開始したことを確認する必要があります。チャンスが来る前にキャンセルされるかもしれません。

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());
    }
}
于 2013-03-02T00:46:13.243 に答える
2

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

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

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

于 2014-07-16T08:08:47.917 に答える
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);
        }
    }
}
于 2017-01-04T14:14:38.477 に答える