Unit test works in debug mode, but does not work during normal operation

Why is my unit test succeeding in debug mode but not working during normal operation?

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()); } } 
+6
source share
5 answers

You must make sure that your task is really running. It can be canceled even if it has a chance.

 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()); } } 
+1
source

The reason almost certainly is because your breakpoint in the debugger stops the main thread, but none of the background threads are those in the ExecutorService. When debugging in eclipse, you can change the breakpoint to stop all threads, not just the main one.

If debugging a job submission and immediate cancellation is so fast that you cancel the task before it starts even once. Try adding a sleep delay between these lines:

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

I know this is old, but I had the same problem. My problem was that I had an IEnumerable which I was listing and checking the output.

When starting the Unit test, IEnumerable returned a different order, which when debugging. This is IEnumerable character, and just adding OrderBy clause solved my problem.

I hope this helps someone, because it can be an unpleasant problem.

+1
source

You must check if all threads are dying before terminating the main thread

 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
source

I had a similar problem when I started my homework from an online course. The grader program from the course I added to the build path used by JUnit4, my version of Eclipse added JUnit5 to any new test cases. I created a new Java project and added JUnit5 to the build bath for my test cases without a grader, and he fixed it for me. Hope this helps.

0
source

All Articles