2013-12-12 17 views
11

Ich versuche Apache HttpClient Interface zu verspotten, um eine der unten genannten Methoden zu verspotten, um ein stubbed JSON-Objekt als Antwort zurückzugeben.Mocking Apache HTTPClient mit Mockito

HttpResponse response = defaultHttpClient.execute(postRequest); 

Kann jemand vorschlagen, wie man dies mit etwas Beispielcode erreicht? Ihre Hilfe würde sehr geschätzt werden.

Dank

Antwort

5

In Ihrer Unit-Test-Klasse müssen Sie defaultHttpClient verspotten:

@Mock 
private HttpClient defaultHttpClient; 

dann sagen Mockito (zum Beispiel in @Before Verfahren), um tatsächlich von Ihrem Mocks zu erstellen:

MockitoAnnotations.initMocks(YourTestClass); 

Dann in Ihrer Testmethode definieren Sie, was execute() Methode zurückgeben sollte:

when(defaultHttpClient.execute(any()/* or wahtever you want here */)).thenReturn(stubbed JSON object); 
+0

Danke das ist brilliant! Aber was ich auch wissen musste, war, ob ich stattdessen DefaultHttpClient oder HttpClient verspotten sollte? –

+0

In mockito können Sie alle nachahmen: Interfaces, abstrakte Klassen, normale Klassen. In Ihrem Fall, wenn Sie das Verhalten von nur 'execute()' Methode simulieren möchten, können Sie die 'HttpClient' Schnittstelle verspotten. Aber wenn Sie Methoden von 'DefaultHttpClient' simulieren möchten, die nicht in' HttpClient' verfügbar sind, müssen Sie die 'DefaultHttpClient' Klasse direkt vortäuschen. –

+0

Danke. Extrem hilfreich. Ich gebe es und bestätigen, wenn es funktioniert .. –

1

Sie können dies einfach mit PowerMockito tun, die auch finale/statische Methoden, private Methoden und anonyme Klassen leicht vortäuschen kann. Hier ist der Beispielcode für eine verspottete http-Anfrage. JSON_STRING_DATA ist eine beliebige Zeichenfolge, die Sie von der execute-Methode erhalten möchten.

PowerMockito.mockStatic(DefaultHttpClient.class); 
    HttpClient defaultHttpClientMocked = PowerMockito.mock(DefaultHttpClient.class);   
    PowerMockito.when(defaultHttpClientMocked.execute(Mockito.any(HttpPost.class))).thenReturn(createMockedHTTPResponse(JSON_STRING_DATA)); 
10

Hier ist, was ich habe meinen Code HttpBuilder mit Mockito und Apache zu testen:

Klasse im Test:

import java.io.BufferedReader; 
import java.io.IOException; 

import javax.ws.rs.core.Response.Status; 

import org.apache.http.HttpResponse; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.impl.client.HttpClientBuilder; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class StatusApiClient { 
private static final Logger LOG = LoggerFactory.getLogger(StatusApiClient.class); 

    private String targetUrl = ""; 
    private HttpClient client = null; 
    HttpGet httpGet = null; 

    public StatusApiClient(HttpClient client, HttpGet httpGet) { 
     this.client = client; 
     this.httpGet = httpGet; 
    } 

    public StatusApiClient(String targetUrl) { 
     this.targetUrl = targetUrl; 
     this.client = HttpClientBuilder.create().build(); 
     this.httpGet = new HttpGet(targetUrl); 
    } 

    public boolean getStatus() { 
     BufferedReader rd = null; 
     boolean status = false; 
     try{ 
      LOG.debug("Requesting status: " + targetUrl); 


      HttpResponse response = client.execute(httpGet); 

      if(response.getStatusLine().getStatusCode() == Status.OK.getStatusCode()) { 
       LOG.debug("Is online."); 
       status = true; 
      } 

     } catch(Exception e) { 
      LOG.error("Error getting the status", e); 
     } finally { 
      if (rd != null) { 
       try{ 
        rd.close(); 
       } catch (IOException ioe) { 
        LOG.error("Error while closing the Buffered Reader used for reading the status", ioe); 
       } 
      } 
     } 

     return status; 
    } 
} 

Test:

import java.io.IOException; 

import org.apache.http.HttpResponse; 
import org.apache.http.StatusLine; 
import org.apache.http.client.ClientProtocolException; 
import org.apache.http.client.HttpClient; 
import org.apache.http.client.methods.HttpGet; 
import org.apache.http.conn.HttpHostConnectException; 
import org.junit.Assert; 
import org.junit.Test; 
import org.mockito.Mockito; 

public class StatusApiClientTest extends Mockito { 

    @Test 
    public void should_return_true_if_the_status_api_works_properly() throws ClientProtocolException, IOException { 
     //given: 
     HttpClient httpClient = mock(HttpClient.class); 
     HttpGet httpGet = mock(HttpGet.class); 
     HttpResponse httpResponse = mock(HttpResponse.class); 
     StatusLine statusLine = mock(StatusLine.class); 

     //and: 
     when(statusLine.getStatusCode()).thenReturn(200); 
     when(httpResponse.getStatusLine()).thenReturn(statusLine); 
     when(httpClient.execute(httpGet)).thenReturn(httpResponse); 

     //and: 
     StatusApiClient client = new StatusApiClient(httpClient, httpGet); 

     //when: 
     boolean status = client.getStatus(); 

     //then: 
     Assert.assertTrue(status); 
    } 

    @Test 
    public void should_return_false_if_status_api_do_not_respond() throws ClientProtocolException, IOException { 
     //given: 
     HttpClient httpClient = mock(HttpClient.class); 
     HttpGet httpGet = mock(HttpGet.class); 
     HttpResponse httpResponse = mock(HttpResponse.class); 
     StatusLine statusLine = mock(StatusLine.class); 

     //and: 
     when(httpClient.execute(httpGet)).thenThrow(HttpHostConnectException.class); 

     //and: 
     StatusApiClient client = new StatusApiClient(httpClient, httpGet); 

     //when: 
     boolean status = client.getStatus(); 

     //then: 
     Assert.assertFalse(status); 
    } 

} 

Was denkst du, f Olks, muss ich etwas verbessern? (Ja, ich weiß, die Kommentare. Das ist etwas, was ich aus meinem Spock Hintergrund gebracht: D) ​​

1

Sie können HttpClientMock betrachten, schrieb ich es für das interne Projekt, aber später beschlossen, Open Source. Es erlaubt Ihnen, Scheinverhalten mit flüssiger API zu definieren und später eine Anzahl von getätigten Anrufen zu verifizieren. Beispiel:

HttpClientMock httpClientMock = new 
HttpClientMock("http://localhost:8080"); 
httpClientMock.onGet("/login?user=john").doReturnJSON("{permission:1}"); 

httpClientMock.verify().get("/login?user=john").called(); 
+0

Das sieht sehr gut aus, aber wie stellen Sie sicher, dass die zu testende Klasse Ihren 'HttpClientMock' anstelle von' HttpClients.createDefault() 'verwendet? – neXus

Verwandte Themen