2010-07-02 5 views
7

Mam następujący kod, który spodziewałem się pomyślnie zakończyć, ale kod kończy się niepowodzeniem w wierszu "fail (" nie powinno być osiągnięte ");". Czy ktoś mógłby wyjaśnić, dlaczego domyślny handler przechwycony wyjątek nie nazywa się:Jak korzystać z przechwyconego podręcznika obsługi wyjątków dla testu wielowątkowego w 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

Dlaczego jest 'fail (" to powinno zawieść ");' linia tam? Czy to jest zamierzone? W ten sposób zatrzask nigdy nie odlicza. – BalusC

+0

@BalusC: tak, to jest zamierzone. Aby poprawnie przejść test, metoda latch.await() powinna przerwać, powodując, że zwróci false. Kod powinien następnie wydrukować komunikat z nieprzechwyconego wyjątku AssertionFailedError, który został zgłoszony w kwestionowanej linii. –

Odpowiedz

12

Ma to związek z faktem, że używasz Executor, aby uruchomić zadanie. Nieprzerwana procedura obsługi wyjątku jest wywoływana tylko wtedy, gdy wątek ma zostać zakończony z powodu niezatrzymanego wyjątku. Jeśli zmienisz implementację, aby użyć zwykłego wątku, aby wątek zakończył się z wyjątkiem, zobaczysz oczekiwane zachowanie.

W zależności od tego, w jaki sposób przesyłasz zadania, wątek executora może przechwytywać wszystkie nalepki i obsługiwać je. W związku z tym wątek nie kończy się z powodu tych wyjątków, a tym samym niezwiązany z obsługą przechwytywania wyjątek. Na przykład: ThreadPoolExecutor.execute (Runnable) uruchomi przechwycony menedżer wyjątków. Jednak ThreadPoolExecutor.submit (Callable) nie. Ponadto, ScheduledThreadPoolExecutor.schedule() również nie (ma to związek z wykorzystaniem FutureTask do implementacji).

Lepszym sposobem uzyskiwania dostępu do nieoczekiwanych wyjątków przy użyciu usługi executora jest Przyszłość.

1

ScheduledThreadPoolExecutor.schedule() przyjmuje argument Runnable/Callable, a nie Thread. Te pierwsze nie mają procedur obsługi wyjątków środowiska wykonawczego. Czy masz blok try/catch dla metody RuntimeException w metodzie run lub call.