2013-08-21 4 views
5

Ich möchte eine Methode eines Mock testen ist, um mit verschiedenen Parametern aufgerufen:Mockito: Wie ein Verfahren zur Überprüfung auf ein Mock mit verschiedenen Parameter, um genannt wird

Ich habe versucht, den folgenden Code verwenden:

InOrder inOrder = inOrder(myobject); 
    inOrder.verify(myobject).println(any(String.class)); 
    inOrder.verify(myobject).println(any(String.class)); 
    inOrder.verify(myobject).println(""); 
    inOrder.verify(myobject).println("myfolder"); 
    inOrder.verify(myobject).println(""); 
    inOrder.verify(myobject).println(System.getProperty("user.home")); 

Doch dies scheint nicht zu arbeiten, wie es mir einen Fehler gab, sagt

inOrder.verify(myobject).println(any(String.class)); 

wurde für 8 mal aufgerufen wurde. Dies ist korrekt, aber es wird nicht auf die Bestellung eingegangen.

Ich möchte überprüfen:

The println method of `myobject` is first called with any string parameter 
    Then it is called with any string parameter again 
    Then it is called by an empty string 
    Then it is called by string "myfolder" 
    ...... 

Wie kann ich das erreichen?

EDIT:

Fehlermeldung ist:

org.mockito.exceptions.verification.VerificationInOrderFailure: 
Verification in order failure: 
printWriter.println(<any>); 
Wanted 1 time: 
-> at com.mycompany.MyUnitTest.mytest(MyrUnitTest.java:107) 
But was 8 times. 
+0

Können Sie uns genau zeigen, was der Fehler sagt? –

+0

Danke. Hinzugefügt die Fehlermeldung. – KKKCoder

+0

Haben Sie versucht, es mit 'inOrder.verify (myobject, mal (2)) aufzurufen. Println (any (String.class));'? –

Antwort

5

Verwenden Sie einen Argument-Captor, um die Argumente in allen Aufrufen von println zu erfassen, und überprüfen Sie dann jeden der erfassten Werte, an denen Sie interessiert sind.

@Captor ArgumentCaptor<String> stringCaptor; 

// ... 

@Test public void myTest() { 

    // ... 

    verify(myobject, 6).println(stringCaptor.capture()); 
    assertEquals("", stringCaptor.getAllValues()[2]); 
    assertEquals("myfolder", stringCaptor.getAllValues()[3]); 
    assertEquals("", stringCaptor.getAllValues()[4]);  
    assertEquals(System.getProperty("user.home"), stringCaptro.getAllValues()[5]); 
1

Nun, ist diese Antwort nicht zu allgemein, und ist auch nicht elegant.

Für mich scheint es das Problem verursacht durch any(String.class) ist gierig, das heißt, es passt alle Arten von Zeichenfolgen. Also habe ich versucht, einen Matcher herzustellen, der zu allen Arten von Saiten passt, mit Ausnahme einiger Ausnahmen: "" or "myfolder" or System.getProperty("user.home"). Und der Code ist:

import static org.mockito.AdditionalMatchers.*; 

inOrder.verify(myobject, times(2)).println(
      and(anyString(), not(
        or(eq(""), or(eq("myfolder"), eq(System.getProperty("user.home"))))))); 

Es ist eine Herausforderung, sich diese zu formatieren lesbar sein (aus unerfindlichen Gründen, kann ich nicht einmal and(...) auf eine lokale Variable extrahieren, weil es eine seltsame Laufzeit Ausnahme von Mockito führt dazu, dass ich Kann Matcher nicht außerhalb von Stubbing oder Verifizierung verwenden).

3

David Wallace Lösung ist die beste, die ich kenne, die Mockito verwendet, aber denken Sie daran, dass Spott ist nicht immer das richtige Werkzeug für den Job.

Wenn Sie können, anstelle von Ihrem Mock, übergeben Sie eine PrintWriter(ByteArrayOutputStream) und überprüfen Sie, ob die ByteArrayOutputStream die Ausgabe entspricht, die Sie erwarten.

@Test public void yourTest() { 
    ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
    PrintWriter writer = new PrintWriter(baos); 
    systemUnderTest.doThing(writer); 

    assertTrue(writer.toString().endsWith(
     "\n\nmyfolder\n\n" + System.getProperty(user.home) + "\n")); 
} 

Dies ist auch wahrscheinlich näher an die Logik, die Sie tatsächlich zu testen sind, die, dass die Ausgabe so aussieht, das ist Sie es erwarten, nicht, dass die Verfahren in genau der richtigen Reihenfolge aufgerufen wurden. Sie können dann beliebig umgestalten, einschließlich des Umstiegs auf eine Vorlage MessageFormatter, oder Erstellen Ihrer Zeilenumbrüche in einem StringBuilder und einmaliges Aufrufen von println. Sie sind auch von jedem isoliert, der einen anderen print oder println() Anruf verwendet, der sonst einen Mockito-basierten Test vereiteln würde.

Sie können auch einen Regex Pattern oder Scanner verwenden, um die Korrektheit zu überprüfen, je nachdem wie spezifisch Ihre Anforderungen sind. Pattern.quote kann Ihnen helfen, Regex-Teilstrings zu entkommen, wenn Sie Ihre erwartete Zeichenfolge programmgesteuert erstellen müssen (wie Sie hier mit user.home tun).

+0

+1 Dieser Test könnte sehr gut mit der JMockit Überprüfungs-API geschrieben werden, aber am Ende ist dies ein Fall von verspotter Überbeanspruchung; das Erfassen der gesamten String-Ausgabe und das Überprüfen, ob es gut geformt ist, vielleicht mit einer Regex, ist eine viel bessere Lösung. –