2012-04-13 12 views
5

Tôi đã có một lớp:Làm thế nào để đơn vị kiểm tra một lớp học sử dụng HttpClient trong Android bằng cách sử dụng khung dựng sẵn?

public class WebReader implements IWebReader { 

    HttpClient client; 

    public WebReader() { 
     client = new DefaultHttpClient(); 
    } 

    public WebReader(HttpClient httpClient) { 
     client = httpClient; 
    } 

    /** 
    * Reads the web resource at the specified path with the params given. 
    * @param path Path of the resource to be read. 
    * @param params Parameters needed to be transferred to the server using POST method. 
    * @param compression If it's needed to use compression. Default is <b>true</b>. 
    * @return <p>Returns the string got from the server. If there was an error downloading file, 
    * an empty string is returned, the information about the error is written to the log file.</p> 
    */ 
    public String readWebResource(String path, ArrayList<BasicNameValuePair> params, Boolean compression) { 
      HttpPost httpPost = new HttpPost(path); 
      String result = ""; 

      if (compression) 
       httpPost.addHeader("Accept-Encoding", "gzip"); 
      if (params.size() > 0){ 
       try { 
        httpPost.setEntity(new UrlEncodedFormEntity(params, "UTF-8")); 
       } catch (UnsupportedEncodingException e1) { 
        e1.printStackTrace(); 
       } 
      } 

      try { 
       HttpResponse response = client.execute(httpPost); 
       StatusLine statusLine = response.getStatusLine(); 
       int statusCode = statusLine.getStatusCode(); 
       if (statusCode == 200) { 
        HttpEntity entity = response.getEntity(); 
        InputStream content = entity.getContent(); 
        if (entity.getContentEncoding() != null 
          && "gzip".equalsIgnoreCase(entity.getContentEncoding() 
            .getValue())) 
         result = uncompressInputStream(content); 
        else 
         result = convertStreamToString(content); 
       } else { 
        Log.e(MyApp.class.toString(), "Failed to download file"); 
       } 
      } catch (ClientProtocolException e) { 
       e.printStackTrace(); 
      } catch (IOException e) { 
       e.printStackTrace(); 
      } 

      return result; 
     } 

    private String uncompressInputStream(InputStream inputStream) 
      throws IOException {...} 

    private String convertStreamToString(InputStream is) {...} 

} 

tôi không thể tìm thấy một cách để kiểm tra nó sử dụng một khung tiêu chuẩn. Đặc biệt, tôi cần phải mô phỏng tổng số internet bị mất từ ​​bên trong thử nghiệm.

Có các đề xuất để tắt Internet theo cách thủ công trong trình mô phỏng khi thực hiện kiểm tra. Nhưng có vẻ như tôi không phải là một giải pháp tốt, bởi vì các bài kiểm tra tự động nên ... tự động.

Tôi đã thêm trường "khách hàng" vào lớp cố gắng giả lập từ bên trong lớp kiểm tra. Nhưng việc thực hiện giao diện HttpClient có vẻ khá phức tạp.

Khung Robolectric cho phép nhà phát triển thử nghiệm Http connection theo như tôi biết. Nhưng tôi đoán có một số cách để viết thử nghiệm như vậy mà không cần sử dụng khung công tác bổ sung lớn như vậy.

Vì vậy, có cách nào ngắn và đơn giản của các lớp thử nghiệm đơn vị sử dụng HttpClient? Bạn đã giải quyết vấn đề này như thế nào trong các dự án của mình?

Trả lời

6

Tôi đã thêm trường "khách hàng" vào lớp cố gắng giả lập từ bên trong lớp kiểm tra. Nhưng việc thực hiện giao diện HttpClient có vẻ khá phức tạp.

Tôi hơi bối rối về tuyên bố này. Từ tiêu đề câu hỏi, bạn đang hỏi về httpClint đơn vị thử nghiệm, bằng cách chế nhạo một FakeHttpClient có thể giúp bạn kiểm tra đơn vị phần khác của ứng dụng ngoại trừ httpClient, nhưng không giúp gì cho httpClient thử nghiệm đơn vị. Những gì bạn cần là một FakeHttpLayer cho httpClient thử nghiệm đơn vị (không có máy chủ từ xa, mạng yêu cầu, do đó đơn vị kiểm thử).

HttpClient Dummy Test:

Nếu bạn chỉ cần kiểm tra hành vi ứng dụng trong các tình huống mà Internet bị mất, sau đó một Android Cụ thử nghiệm cổ điển là đủ, bạn có thể lập trình chuyển Internet trong giả lập ra trong khi thực hiện các bài kiểm tra:

public void testWhenInternetOK() { 
    ... ... 
    webReader.readWebResource(); 
    // expect HTTP 200 response. 
    ... ... 
} 

public void testWhenInternetLost() { 
    ... ... 
    wifiManager = (WifiManager) this.getSystemService(Context.WIFI_SERVICE); 
    wifiManager.setWifiEnabled(false); 
    webReader.readWebResource(); 
    // expect no HTTP response. 
... ... 
} 

Điều này đòi hỏi các máy chủ http xa là hoàn toàn thiết lập và trong trạng thái làm việc, và bất cứ khi nào bạn chạy lớp thử nghiệm của bạn, một thông tin liên lạc http thực được thực hiện qua mạng và đánh vào máy chủ http.

HttpClient nâng cao Kiểm tra:

Nếu bạn muốn kiểm tra hành vi ứng dụng chính xác hơn, ví dụ, bạn muốn kiểm tra cuộc gọi http trong bạn ứng dụng để xem nếu nó là xử lý phản ứng khác nhau http đúng cách. Robolectric là lựa chọn tốt nhất. Bạn có thể sử dụng FakeHttpLayer và giả lập yêu cầu http và trả lời cho bất cứ điều gì bạn thích.

public void setup() { 
    String url = "http://..."; 
    // First http request fired in test, mock a HTTP 200 response (ContentType: application/json) 
    HttpResponse response1 = new DefaultHttpResponseFactory().newHttpResponse(HttpVersion.HTTP_1_1, 200, null); 
    BasicHttpEntity entity1 = new BasicHttpEntity(); 
    entity1.setContentType("application/json"); 
    response1.setEntity(entity1); 
    // Second http request fired in test, mock a HTTP 404 response (ContentType: text/html) 
    HttpResponse response2 = new DefaultHttpResponseFactory().newHttpResponse(HttpVersion.HTTP_1_1, 404, null); 
    BasicHttpEntity entity2 = new BasicHttpEntity(); 
    entity2.setContentType("text/html"); 
    response2.setEntity(entity2); 
    List<HttpResponse> responses = new ArrayList<HttpResponse>(); 
    responses.add(response1); 
    responses.add(response2); 
    Robolectric.addHttpResponseRule(new FakeHttpLayer.UriRequestMatcher("POST", url), responses); 
} 

public void testFoo() { 
    ... ... 
    webReader.readWebResource(); // <- a call that perform a http post request to url. 
    // expect HTTP 200 response. 
    ... ... 
} 

public void testBar() { 
    ... ... 
    webReader.readWebResource(); // <- a call that perform a http post request to url. 
    // expect HTTP 404 response. 
... ... 
} 

Một số ưu điểm trong việc sử dụng Robolectric là: kiểm tra

  • Hoàn toàn JUnit, không kiểm tra cụ do đó, không cần phải bắt đầu giả lập (hoặc thiết bị thực) để chạy thử nghiệm, tăng tốc độ phát triển.
  • Mới nhất hỗ trợ Robolectric dòng mã để kích hoạt/vô hiệu hóa FakeHttpLayer, nơi bạn có thể đặt http yêu cầu được giải thích bởi FakeHttpLayer (không thực sự gọi qua mạng), hoặc đặt yêu cầu http bỏ qua FakeHttpLayer (thực hiện cuộc gọi http thực mạng). Hãy xem this SO question để biết thêm chi tiết.

Nếu bạn xem nguồn Robolectric, bạn có thể thấy khá phức tạp khi tự mình triển khai FakeHtppLayer đúng cách. Tôi khuyên bạn nên sử dụng khung kiểm tra hiện có thay vì triển khai API của riêng bạn.

Hy vọng điều này sẽ hữu ích.

+0

Cảm ơn câu trả lời của bạn. Vâng, tiêu đề nói về kiểm tra đơn vị một số lớp có sử dụng HttpClient, tôi không có nghĩa là thử nghiệm HttpClient rất. Xin lỗi, nếu tôi không nói rõ. Tùy chọn với trình quản lý WiFi rất tuyệt, nhưng điện thoại vẫn giữ kết nối qua mạng di động. Tôi đã thử chế độ trên máy bay, nó vẫn đang kết nối. Vì vậy, tôi đoán, Robolectric là sự lựa chọn duy nhất. Cảm ơn bạn. –

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