2012-04-13 5 views
5

Tengo una clase:¿Cómo probar la unidad de una clase que usa HttpClient en Android utilizando el marco integrado?

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) {...} 

} 

no puedo encontrar una manera de probar que el uso de un marco estándar. Especialmente, necesito simular la pérdida total de Internet desde el interior de la prueba.

Existen sugerencias para desactivar manualmente Internet en el emulador mientras se realiza la prueba. Pero me parece que no es una solución bastante buena, porque las pruebas automáticas deberían ser ... automáticas.

Agregué un campo de "cliente" a la clase tratando de simularlo desde el interior de la clase de prueba. Pero la implementación de la interfaz HttpClient parece bastante compleja.

El marco Robolectric permite a los desarrolladores probar Http connection hasta donde yo sé. Pero creo que hay alguna manera de escribir una prueba de este tipo sin usar un marco adicional tan grande.

¿Existen algunas formas breves y sencillas de probar unidades de clases que usan HttpClient? ¿Cómo resolviste esto en tus proyectos?

Respuesta

6

Agregué un campo de "cliente" a la clase intentando simularlo desde dentro de la clase de prueba. Pero la implementación de la interfaz HttpClient parece bastante compleja.

Estoy un poco confundido acerca de esta afirmación. Del título de la pregunta, usted está preguntando sobre la prueba unitaria de httpClint, burlándose de FakeHttpClient puede ayudarlo a realizar pruebas unitarias en otra parte de la aplicación, excepto httpClient, pero no ayuda en nada a la prueba unitaria de httpClient. Lo que necesita es un FakeHttpLayer para pruebas unitarias de httpClient (no requiere servidor remoto, la red lo requiere, por lo tanto, pruebas unitarias).

HttpClient simulado de la prueba:

Si sólo necesita examinar el comportamiento de la aplicación en la situación de que Internet se pierde, a continuación, un clásico de prueba del instrumento Android es suficiente, puede activar mediante programación en Internet en el emulador fuera mientras se realiza la prueba:

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. 
... ... 
} 

Esto requiere que el servidor HTTP remoto es totalmente configuración y en un estado de trabajo, y cada vez que se ejecuta la clase de prueba, una comunicación http verdadera se hace a través de red y golpeado en el servidor http.

HttpClient test avanzado:

Si desea probar el comportamiento de aplicación más precisa, por ejemplo, que desea probar una llamada http en ti aplicación para ver si se trata de manejar diferentes de respuesta HTTP correctamente. Robolectric es la mejor opción. Puede usar FakeHttpLayer y simular la solicitud y respuesta http a lo que quiera.

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. 
... ... 
} 

Algunas ventajas de la utilización de Robolectric son: Prueba de

  • puramente JUnit, ninguna prueba instrumento de forma no es necesario empezar emulador (o dispositivo real) para ejecutar la prueba, aumentar la velocidad de desarrollo.
  • La última línea de código compatible con Robolectric para habilitar/deshabilitar FakeHttpLayer, donde puede configurar la solicitud http para ser interpretada por FakeHttpLayer (no real llamada http sobre la red), o establecer la solicitud http omitir el FakeHttpLayer (realizar real http llamada sobre red). Consulte this SO question para más detalles.

Si consulta la fuente de Robolectric, verá que es bastante complejo implementar una aplicación FakeHtppLayer correctamente. Yo recomendaría utilizar el marco de prueba existente en lugar de implementar su propia API.

Espero que esto ayude.

+0

Gracias por su respuesta. Bueno, el título dice sobre la unidad de prueba de una clase que utiliza HttpClient, no me refiero a probar el HttpClient. Lo siento, si no lo dejé claro. La opción con el administrador WiFi es excelente, pero el teléfono se sigue conectando a través de la red móvil. He probado un modo de avión, todavía está conectando. Entonces, supongo, Robolectric es la única opción. Gracias. –

Cuestiones relacionadas