2010-09-13 9 views
9

Bei Versuchen von 100% Code-Coverage, stieß ich auf eine Situation, in der ich Block Code testen muss, die eine InterruptedException fängt. Wie testet man das richtig? (JUnit 4 Syntax bitte)Wie Unit-Test schreiben für "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(); 
     } 
    } 
} 

Antwort

13

Kurz vor addMessage() Aufruf, rufen Thread.currentThread().interrupt(). Dadurch wird das Flag "Interrupt" für den Thread gesetzt.

Wenn der unterbrochene Zustand gesetzt wird, wenn der Anruf an put() auf einem LinkedBlockingQueue gemacht wird, wird ein InterruptedException erhöht werden, auch wenn kein Warten auf das put erforderlich ist (das Schloss ist un-stritten).

Übrigens sind einige Bemühungen, eine 100% ige Abdeckung zu erreichen, kontraproduktiv und können die Qualität des Codes sogar verschlechtern.

+1

+1, das ist wahr. Ziel für 80-85 und Sie werden alle Probleme wie diese vermeiden und Ihren Code immer noch unberührt lassen. – BjornS

+1

Dies ist eine ziemlich brutale Lösung und könnte unerwartete Nebenwirkungen haben. Ich fand zum Beispiel, dass das Aufrufen von Thread.currentThread() .interrupt() in einer Testmethode alle Testmethoden in der gleichen Klasse betrifft, was dazu führt, dass alle anderen Tests fehlschlagen. Ich fand auch, dass das Hinzufügen dieses zu jeder Testklasse Sonar veranlassen würde, 0% Unit Test Coverage zu melden (habe nicht herausgefunden, warum). – RCross

+0

Ja, Sie müssen vorsichtig sein, wo Sie es benutzt haben, stellen Sie sicher, dass der Interrupt-Status gelöscht wird (wie hier) und dass es keine Zwischenprüfung des Status zwischen Ihrer Einstellung und der Überprüfung Ihres Tests gibt. – erickson

9

eine spöttische Bibliothek wie EasyMock verwenden und ein Mock LinkedBlockingQueue

dh mit InterruptedException zu Guava ‚s Uninterruptibles,

@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

Absolut der beste Weg. Löst viel mehr Probleme als dies auch. –

1

Eine weitere Option ist zu delegieren Umgang injizieren, so dass Sie brauchen nicht zu Schreiben und testen Sie Ihren benutzerdefinierten Code dafür:

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

private final LinkedBlockingQueue<ExampleMessage> queue; 

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