2010-09-13 14 views
9

In tentativi di copertura del 100% del codice, mi sono imbattuto in una situazione in cui ho bisogno di unità blocco di codice di prova che cattura uno InterruptedException. Come fa una unità correttamente a testare questo? (JUnit 4 sintassi si prega)Come scrivere test unitario per "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(); 
     } 
    } 
} 

risposta

13

destro prima di richiamare addMessage(), chiamare Thread.currentThread().interrupt(). Questo imposterà il flag di stato "interrupt" sul thread.

Se lo stato interrotto viene impostato quando la chiamata a put() viene effettuata su un LinkedBlockingQueue, sarà sollevato un InterruptedException, anche se è richiesta nessuna attesa per il put (il blocco è un-sostenuto).

Tra l'altro, alcuni sforzi per raggiungere una copertura del 100% sono controproducenti e possono effettivamente degradare la qualità del codice.

+1

+1, questo è vero. Punta 80-85 e eviterete tutti i problemi come questo e continuate a mantenere il vostro codice piuttosto intatto. – BjornS

+1

Questa è una soluzione piuttosto brutale e potrebbe avere effetti collaterali inaspettati. Ad esempio, ho scoperto che chiamare Thread.currentThread(). Interrupt() in un metodo di test influirebbe su tutti i metodi di test nella stessa classe, causando il fallimento di tutti gli altri test. Ho anche scoperto che l'aggiunta di questo a qualsiasi classe di test causerebbe a Sonar di segnalare una copertura del test dell'unità dello 0% (non hanno scoperto il motivo). – RCross

+0

Sì, dovresti stare attento a dove lo hai usato, assicurandoti che lo stato dell'interrupt sia cancellato (come è qui) e che non ci sia un controllo intermedio dello stato tra le tue impostazioni e il controllo del test su di esso. – erickson

9

utilizzare una libreria beffardo come EasyMock e iniettare un LinkedBlockingQueue finto

cioè

@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

Assolutamente il modo migliore. Risolve molti più problemi di questo. –

1

Un'altra opzione è quella di delegare trattare con InterruptedException per Guava s' Uninterruptibles, quindi non c'è bisogno di scrivi e prova il tuo codice personalizzato per questo:

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

private final LinkedBlockingQueue<ExampleMessage> queue; 

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