2010-09-13 12 views
9

En intentos de cobertura de código 100%, me encontré con una situación en la que necesito un bloque de código de prueba de unidad que captura un InterruptedException. ¿Cómo puede una unidad probar esto correctamente? (JUnit 4 sintaxis favor)Cómo escribir la prueba de unidad para "InterruptedException"

private final LinkedBlockingQueue<ExampleMessage> m_Queue; 

public void addMessage(ExampleMessage hm) { 
    if(hm!=null){ 
     try { 
      m_Queue.put(hm); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } 
    } 
} 

Respuesta

13

Justo antes de invocar addMessage(), llame Thread.currentThread().interrupt(). Esto establecerá el indicador de estado de "interrupción" en el hilo.

Si el estado se establece cuando interrumpe la llamada a put() se hace en un LinkedBlockingQueue, un InterruptedException serán levantados, aunque no se requiere de espera para el put (el bloqueo es un-contendió).

Por cierto, algunos esfuerzos para alcanzar el 100% de cobertura son contraproducentes y en realidad pueden degradar la calidad del código.

+1

+1, esto es cierto. Intenta 80-85 y evitarás todos los problemas como este y aún así mantendrás tu código bastante prístino. – BjornS

+1

Esta es una solución bastante brutal y podría tener efectos secundarios inesperados. Por ejemplo, encontré que llamar a Thread.currentThread(). Interrupt() en un método de prueba afectaría todos los métodos de prueba en la misma clase, haciendo que todas las demás pruebas fallen. También encontré que al agregar esto a cualquier clase de prueba, Sonar informaría un 0% de cobertura de prueba unitaria (no se ha descubierto por qué). – RCross

+0

Sí, tendrías que tener cuidado donde lo usaste, asegurándote de que el estado de interrupción se borrará (como está aquí) y de que no hay una verificación intermedia del estado entre tu configuración y la comprobación de la prueba. – erickson

9

utilizar una biblioteca de burla como EasyMock e inyectar un simulacro LinkedBlockingQueue

es decir

@Test(expect=InterruptedException.class) 
public void testInterruptedException() { 
    LinkedBlockingQueue queue = EasyMock.createMock(LinkedBlockingQueue.class); 
    ExampleMessage message = new ExampleMessage(); 
    queue.put(message); 
    expectLastCall.andThrow(new InterruptedException()); 
    replay(queue); 
    someObject.setQueue(queue); 
    someObject.addMessage(msg); 
} 
+0

Absolutamente la mejor manera. Resuelve muchos más problemas que esto también. –

1

Otra opción es delegar a tratar con InterruptedExceptionguayaba 's Uninterruptibles, por lo que no es necesario escriba y pruebe su código personalizado para ello:

import static com.google.common.util.concurrent.Uninterruptibles.putUninterruptibly; 

private final LinkedBlockingQueue<ExampleMessage> queue; 

public void addMessage(ExampleMessage message) { 
    putUninterruptibly(queue, message); 
}