2013-03-02 7 views
6

Warum ist der Komponententest erfolgreich im Debugmodus, aber fehlgeschlagen, wenn er normal ausgeführt wird?Komponententest ist erfolgreich im Debugmodus, schlägt aber bei normalem Betrieb fehl

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

Vorschlag, versuchen Sie die 'unterbrocheneBitSet'' flüchtige' – yohlulz

+0

Dies hat nicht funktioniert. –

+0

Wo ist Ihr Haltepunkt beim Debuggen? – Alb

Antwort

1

Sie müssen sicherstellen, dass Ihre Aufgabe tatsächlich ausgeführt wurde. Es kann abgebrochen werden, bevor es überhaupt eine Chance hat.

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

Der Grund ist fast sicher, dass Ihr Haltepunkt im Debugger den Haupt-Thread zu stoppen, aber nicht der Hintergrund-Threads - die, die in der ExecutorService. Beim Debuggen in Eclipse können Sie den Haltepunkt so ändern, dass alle Threads angehalten werden und nicht nur der Hauptpunkt.

Wenn Sie nicht debuggen die Einreichung der Aufgabe und die sofortige Stornierung sind so schnell, dass Sie die Aufgabe abbrechen, bevor es einmal ausgeführt wird. Versuchen Sie, eine Schlafverzögerung zwischen diesen Zeilen hinzuzufügen:

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

Warum sieht der Hauptthread das geänderte Flag (modifiziert durch den erzeugten Thread) im Freigabemodus nicht? –

+0

Lassen Sie mich klarstellen: Ich habe es in der Testmethode auf "disruptedBitSet = false" gesetzt, nicht Calless() -Methode Callable. –

+0

@ Chris-Morris sorry, ich habe den Code zuerst falsch gelesen, ich habe meine Antwort mit einem anderen Vorschlag bearbeitet – Alb

1

Ich weiß, das ist alt, aber ich hatte gerade das gleiche Problem. Mein Problem war, dass ich eine IEnumerable hatte, die ich aufzählte und die Ausgabe prüfte.

Beim Ausführen des Komponententests gab IEnumerable eine andere Reihenfolge als beim Debugging zurück. Dies ist die Natur IEnumerable und einfach eine OrderBy Klausel hinzugefügt löste mein Problem.

Ich hoffe, dass dies jemand da draußen hilft, da es ein frustrierendes Problem sein kann, zu finden.

0

sollten Sie prüfen, ob alle Fäden stirbt, bevor der Haupt-Thread beendet

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

ich ein ähnliches Problem wurde, während eine Hausaufgabe von einem Online-Kurs läuft. Das Grader-Programm aus dem Kurs, den ich zum Build-Pfad hinzugefügt habe, verwendete JUnit4, meine Version von Eclipse fügte JUnit5 zu neuen Testfällen hinzu. Ich habe ein neues Java-Projekt erstellt und JUnit5 zum Build-Bad für meine Testfälle ohne den Grader hinzugefügt und es für mich repariert. Hoffe das hilft.