2016-08-02 41 views
1

Ich möchte mit Mockito folgenden Code testen:Kann nicht spotten java.io.Reader lesen

public static String funcToTest(String query) throws Exception { 
    String url = Config.getURL(serviceName); 
    HttpClient client = new HttpClient(); 
    HttpMethod method = new GetMethod(url); 
    String resultantString= ""; 

    method.setQueryString(URIUtil.encodeQuery(query)); 
    client.executeMethod(method); 
    if (method.getStatusCode() == HttpStatus.SC_OK) { 
     Reader reader = new InputStreamReader(method 
        .getResponseBodyAsStream()); 
     int charValue = 0; 
     StringBuffer sb = new StringBuffer(1024); 
     while ((charValue = reader.read()) != -1) { 
      sb.append((char) charValue); 
     } 
     resultantString = sb.toString(); 
    } 
    method.releaseConnection(); 
    return resultantString; 
} 

ich den Test erstellt wie folgt vor:

@Test 
public void testFunc() throws Exception{ 
    HttpMethod method = Mockito.mock(HttpMethod.class); 
    InputStream inputStream = Mockito.mock(InputStream.class); 
    Reader reader = Mockito.mock(Reader.class); 

    when(method.getResponseBodyAsStream()).thenReturn(inputStream); 
    PowerMockito.whenNew(Reader.class).withArguments(eq(inputStream)).thenReturn(reader); 

    Mockito.when(reader.read()).thenReturn((int)'1', -1); 


    String actualResult = cls.funcToTest(""); 
    String expected = "1"; 
    assertEquals(expected, actualResult); 
} 

Aber die reader.read() Methode wird nicht zurückkehren 1. Stattdessen gibt es immer -1 zurück. Wie sollte ich Reader so vortäuschen, dass read() Methode etwas anderes als -1 zurückgibt.

Danke. spöttisch zu mock Funktion lokale Variablen/Referenzen

Antwort

0

Es muss funktionieren, tut mir leid, was Sie etwas verwirrt machen

)
// annotations is very important, cls I your tested class name, i assume cls is yours 

@RunWith(PowerMockRunner.class) 
@PrepareForTest({cls.class}) 
public class PrinterTest { 

    @Test 
    public void print() throws Exception { 

     String url = ""; 
     GetMethod method = Mockito.mock(GetMethod.class); 
     InputStream inputStream = Mockito.mock(InputStream.class); 
     InputStreamReader reader = Mockito.mock(InputStreamReader.class); 

     Mockito.when(method.getResponseBodyAsStream()).thenReturn(inputStream); 
     //forgot about it) 
     PowerMockito.whenNew(GetMethod.class).withArguments(eq(url)).thenReturn(method); 
     PowerMockito.whenNew(InputStreamReader.class).withArguments(eq(inputStream)).thenReturn(reader); 


     Mockito.when(reader.read()).thenReturn((int) '1', -1); 
     when(method.getStatusCode()).thenReturn(HttpStatus.SC_OK); 

     String actualResult = cls.funcToTest(url); 
     String expected = "1"; 
     assertEquals(expected, actualResult); 
    } 


} 
+0

'System.out.println (inputStream.read());' druckt 1, aber 'resultReader.read()' Methode innerhalb while-Schleife gibt -1 jedes Mal zurück. Es ist also immer leer. – Emi

+0

Bitte aktualisieren Sie Ihren Beitrag und geben Sie ganze getestete Klasse, es ist jetzt sehr vage. Aber Ihre Ausgabe ist -1, weil Sie Ihr Mock-Objekt nicht in der echten Methode übergeben, sondern einen anderen Eingabestream erstellen. Versuchen Sie PowerMockito.whenNew (InputStreamReader.class) .withArguments (eq (expectedArg1), eq (expectedArg2), ...). ThenReturn (expectedReader); es wird Ihnen helfen, injizieren Sie Ihre mock –

+0

Ich habe bereits versucht 'PowerMockito.whenNew (InputStreamReader.class) .withArguments (inputStream) .thenReturn (Leser);', aber hier machen wir neue auf InputStreamReader-Klasse und erhalten Reader-Objekt. Es gibt also einen Fehler für nicht übereinstimmende Argumente. NB. Ich habe die Frage aktualisiert. – Emi

1

Zunächst einmal Ihre Testcode eine Menge .class tut. Verspotten ist für Klassenabhängigkeiten und nicht für funktionale lokale Variablen.

Wie geschrieben, können Sie nicht Ihre Funktion funcToTest mit Mocking allein testen. Sie müssen diese Funktion neu schreiben, wenn Sie keine echten Objekte für - HttpMethod & Reader verwenden möchten.

Sie müssen den Objekt-Erstellungscode mit new außerhalb dieser Funktion entfernen, wenn Sie Aufrufe dieser Objekte simulieren und den Code new durch diese get-Methode ersetzen möchten. z.B.

protected HttpMethod getHttpMethod(String Url){ 
    return new GetMethod(url); 
} 

Auch sehe ich nicht, dass Sie diese Zeile für eine gefälschte URL verspotten - es scheint notwendig für Unit-Tests.

String url = Config.getURL(serviceName); 

Nach Objekterstellung Code außerhalb Ihrer Funktion übernommen haben, müssen Sie eine neue Klasse erstellen, als Ihre SUT (Subject Under Test) erstreckt und Sie diese Methoden außer Kraft setzen (getHttpMethod) gefälschte/verspottet Instanzen zu schaffen.

Sie müssen ähnliche Methode schreiben, um Reader Instanz zu erhalten.

Dann testen Sie diese neue Klasse - erweitert von Ihrem SUT, da die Logik zur Erstellung von Objekten nicht getestet werden muss.

Ohne Objekt erstellen Code außerhalb der Funktion, sehe ich keine Möglichkeit, es durch Mockito verspotten.

Hoffe es hilft !!