代码之家  ›  专栏  ›  技术社区  ›  Chris Morris

单元测试在调试模式下成功,但在正常运行时失败

  •  14
  • Chris Morris  · 技术社区  · 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());
      }
    }
    
    5 回复  |  直到 13 年前
        1
  •  3
  •   Alb    13 年前

    原因几乎可以肯定的是,调试器中的断点正在停止主线程,而不是任何后台线程,即ExecutorService中的后台线程。在eclipse中调试时,可以更改断点以停止所有线程,而不仅仅是主线程。

    当不调试时,任务的提交和立即取消非常快,以至于您甚至在任务运行一次之前就取消了任务。尝试在以下行之间添加睡眠延迟:

    final Future<String> future =  pool.submit(new TaskChecksForInterruptedBit());
    Thread.sleep(1000);
    final boolean wasJustCancelled = future.cancel(true);
    
        2
  •  2
  •   jdb    13 年前

    你必须确保你的任务真的开始运行了。它甚至可能在有机会之前就被取消了。

    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
  •  2
  •   Talon    11 年前

    我知道这是旧的,但我只是遇到了同样的问题。 我的问题是我有一个 IE可数 我正在枚举和检查输出。

    运行单元测试时 IE可数 正在返回与调试时不同的顺序。这就是 IE可数 并简单地添加 排序 条款解决了我的问题。

    我希望这能帮助到其他人,因为这可能是一个令人沮丧的问题。

        4
  •  0
  •   Bhavesh    9 年前

    在终止主线程之前,您应该检查是否所有线程都已失效

    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);
            }
        }
    }
    
        5
  •  0
  •   Andre Guerra    8 年前

    我在网上做作业时也遇到了类似的问题。我添加到构建路径中的课程中的分级程序使用了JUnit4,我的Eclipse版本将JUnit5添加到任何新的测试用例中。我创建了一个新的Java项目,并在没有分级器的情况下将JUnit5添加到我的测试用例的构建槽中,它为我修复了它。希望这能有所帮助。