2013-12-12 14 views
11

Tôi đang cố gắng giả lập Giao diện Apache HttpClient để mô phỏng một trong các phương thức được đề cập dưới đây để trả về một đối tượng JSON được trả lời đáp ứng.Chế nhạo Apache HTTPClient bằng Mockito

HttpResponse response = defaultHttpClient.execute(postRequest); 

Ai đó có thể đề xuất cách đạt được điều này với một số mã mẫu? Giúp đỡ của bạn sẽ được đánh giá rất nhiều.

Cảm ơn

Trả lời

5

Trong lớp thử nghiệm đơn vị của bạn, bạn cần phải thử defaultHttpClient:

@Mock 
private HttpClient defaultHttpClient; 

Sau đó bạn nói với Mockito (ví dụ như trong @Before phương pháp) để thực sự tạo mocks của bạn bằng cách:

MockitoAnnotations.initMocks(YourTestClass); 

Sau đó, trong phương pháp thử, bạn xác định phương thức execute() sẽ trả về:

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

Cảm ơn điều đó thật tuyệt vời! Nhưng những gì tôi cũng cần biết là liệu tôi có nên chế nhạo DefaultHttpClient hoặc HttpClient thay thế không? –

+0

Trong mockito bạn có thể giả lập tất cả: giao diện, lớp trừu tượng, các lớp bình thường. Trong trường hợp của bạn, nếu bạn muốn mô phỏng hành vi của phương thức 'execute()', bạn có thể giả lập giao diện 'HttpClient'. Nhưng nếu bạn muốn mô phỏng các phương thức từ 'DefaultHttpClient' không có sẵn trong' HttpClient', bạn phải giả lập lớp 'DefaultHttpClient' trực tiếp. –

+0

Cảm ơn. Vô cùng hữu ích. Tôi sẽ cung cấp cho nó một đi và xác nhận nếu nó hoạt động .. –

1

Bạn có thể thực hiện điều này dễ dàng bằng PowerMockito, cũng có thể thử các phương thức cuối cùng/tĩnh, phương thức riêng và các lớp ẩn danh dễ dàng. Đây là mã mẫu để yêu cầu http giả mạo. JSON_STRING_DATA là bất kỳ chuỗi nào bạn muốn nhận từ phương thức thực thi.

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

Dưới đây là những gì tôi đã làm để kiểm tra mã của tôi sử dụng Mockito và Apache HttpBuilder:

Class dưới kiểm tra:

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); 
    } 

} 

Bạn nghĩ gì về f olks, tôi cần phải cải thiện một cái gì đó? Đó là điều tôi mang từ nền Spock của tôi: D)

1

Bạn có thể xem HttpClientMock, tôi đã viết nó cho dự án nội bộ nhưng sau đó đã quyết định mở nguồn. Nó cho phép bạn xác định hành vi giả lập với API thông thạo và sau đó xác minh một số cuộc gọi được thực hiện. Ví dụ:

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

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

Điều đó có vẻ rất đẹp, nhưng làm thế nào để bạn đảm bảo rằng lớp được thử nghiệm sử dụng 'HttpClientMock' của bạn thay vì' HttpClients.createDefault() '? – neXus

Các vấn đề liên quan