2010-07-02 4 views
7

J'ai le code suivant que je m'attends à terminer avec succès mais le code échoue à la ligne "fail (" cela ne devrait pas être atteint ");". Quelqu'un peut-il s'il vous plaît expliquer pourquoi le défaut gestionnaire d'exceptions est uncaught pas appelé:Comment utiliser un gestionnaire d'exception non intercepté pour un test multi-thread dans junit?

public class UncaughtExceptionTest extends TestCase 
    implements UncaughtExceptionHandler { 

    private final List<Throwable> uncaughtExceptions = 
     new CopyOnWriteArrayList<Throwable>(); 

    class UncaughtExceptionTestInnerClass implements Runnable { 
     private final ScheduledThreadPoolExecutor executor = 
      new ScheduledThreadPoolExecutor(1); 
     private final CountDownLatch latch; 

     UncaughtExceptionTestInnerClass(CountDownLatch latch) { 
      this.latch = latch; 
      executor.schedule(this, 50, TimeUnit.MILLISECONDS); 
     } 

     @Override 
     public void run() { 
      System.out.println("This is printed"); 
      fail("this should fail"); 
      latch.countDown(); 
     } 
    } 

    @Test 
    public void testUncaughtExceptions() { 
     Thread.setDefaultUncaughtExceptionHandler(this); 
     CountDownLatch latch = new CountDownLatch(1); 
     UncaughtExceptionTestInnerClass testTheInnerClass = 
       new UncaughtExceptionTestInnerClass(latch); 
     try { 
      if (!latch.await(1, TimeUnit.SECONDS)) { 
       if (uncaughtExceptions.size() > 0) { 
        Throwable exception = uncaughtExceptions.get(0); 
        System.out.println("First uncaught exception: " + 
            exception.getMessage()); 
       } 
       else { 
        fail("this should not be reached"); 
       } 
      } 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 

    @Override 
    public void uncaughtException(Thread t, Throwable e) { 
     uncaughtExceptions.add(e); 
    } 
} 
+0

Pourquoi le 'fail (" ceci devrait échouer ");' line there? Est-ce intentionnel? De cette façon, le verrou ne décompte jamais. – BalusC

+0

@BalusC: oui, c'est intentionnel. Pour réussir le test, la méthode latch.await() doit expirer, provoquant le retour de false. Le code doit ensuite imprimer le message de l'exception uncaught de AssertionFailedError qui a été jeté sur la ligne que vous remettez en question. –

Répondre

12

Il a à voir avec le fait que vous utilisez un Exécuteur pour exécuter la tâche. Le gestionnaire d'exceptions non interceptées est appelé uniquement si le thread est sur le point d'être arrêté en raison d'une exception non interceptée. Si vous modifiez votre implémentation pour utiliser un thread simple afin que le thread se termine avec l'exception, vous verrez le comportement attendu.

Selon la façon dont vous soumettez des tâches, le thread exécuteur peut capturer tous les Throwables et les gérer. Par conséquent, le thread ne se termine pas à cause de ces exceptions et le gestionnaire d'exceptions non interceptées n'est donc pas impliqué. Par exemple, ThreadPoolExecutor.execute (exécutable) déclenchera le gestionnaire d'exceptions non interceptées. Cependant, ThreadPoolExecutor.submit (Callable) ne l'est pas. En outre, ScheduledThreadPoolExecutor.schedule() ne soit pas (il doit faire avec leur utilisation de FutureTask pour la mise en œuvre).

Une meilleure façon d'accéder à des exceptions inattendues avec un service d'exécution est via Future.

1

prend un Runnable/Callable argument, pas Thread. Les premiers n'ont pas de gestionnaires d'exceptions d'exécution. Un bloc try/catch pour un RuntimeException dans votre méthode run ou call.

Questions connexes