2010-07-02 19 views
7

Tengo el siguiente código que espero que se ejecute correctamente hasta la finalización, pero el código falla en la línea "error (" no se debe alcanzar ");". Por favor alguien puede explicar por qué la excepción no capturada por defecto no se llama:¿Cómo utilizar un controlador de excepciones no detectadas para una prueba de múltiples hilos en 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

¿Por qué falla la línea 'fail (" this should fail ");'? Es esto intencional? De esta forma, el pestillo nunca cuenta hacia abajo. – BalusC

+0

@BalusC: sí, esto es intencional. Para pasar la prueba correctamente, el método latch.await() debe expirar, haciendo que devuelva falso. El código debería imprimir el mensaje de la excepción AssertionFailedError no detectada que se lanzó en la línea que está cuestionando. –

Respuesta

12

Tiene que ver con el hecho de que está utilizando una Ejecutor para ejecutar la tarea. El controlador de excepciones no detectadas se invoca solo si el hilo está a punto de finalizar debido a una excepción no detectada. Si cambia su implementación para usar un hilo simple para que el hilo termine con la excepción, verá el comportamiento esperado.

Dependiendo de cómo envíe las tareas, el hilo ejecutor puede capturar todas las Throwables y manejarlas. Por lo tanto, el subproceso no finaliza debido a estas excepciones y, por lo tanto, el manejador de excepciones no detectadas no se involucra. Por ejemplo, ThreadPoolExecutor.execute (ejecutable) activará el controlador de excepciones no detectadas. Sin embargo, ThreadPoolExecutor.submit (llamable) no lo hace. Además, ScheduledThreadPoolExecutor.schedule() tampoco (tiene que ver con su uso de FutureTask para la implementación).

Una mejor forma de acceder a las excepciones inesperadas con un servicio de ejecutor es a través de Future.

1

ScheduledThreadPoolExecutor.schedule() toma un argumento Runnable/Callable, no Thread. Los primeros no tienen controladores de excepciones en tiempo de ejecución. Tenga un bloque try/catch para RuntimeException en su método run o call.

Cuestiones relacionadas