Estoy tratando de hacer algunas pruebas unitarias, y todavía no me he conformado con un corredor o una clase de prueba.

Al final, este es el método que estoy verificando que funcione:

public static void getData(final Context context, final Callback<MyObject> callback) {

    Locale locale = context.getResources().getConfiguration().locale;
    MyObjectService myService = new MyObjectService(getRequestHeaders(context), locale);
}

Entonces necesito un contexto simulado que tenga recursos, configuración, configuración regional y SharedPreferences.

Probé PowerMockito, AndroidTestCase, AndroidTestRunner, ApplicationTestCase. Todo lo que puedo obtener es un contexto simulado sin nada en él, o recursos simulados, pero no puedo averiguar cómo agregarlos al contexto simulado (básicamente, rehacer un contexto).

Este es actualmente mi último intento (aunque he probado otros más complejos, sin éxito):

Import com.myApp.android.app.shop.util.ServiceUtils;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mockito;
import org.powermock.modules.junit4.PowerMockRunner;

import android.content.Context;

@RunWith(PowerMockRunner.class)
public class TestLogin
{
    @Test
    public void test()
    {
        Context context = Mockito.mock(Context.class);
        ServiceUtils.getData(context, dataCallback);
    }
}

La excepción que obtengo es un NPE de getData () ya que el contexto pasado no tiene recursos.

¿Alguna sugerencia?

0
TooManyEduardos 25 ene. 2016 a las 22:49

3 respuestas

La mejor respuesta

Android no es un sistema fácilmente burlable. Yo también he intentado usar Mockito para simular el marco, pero rápidamente se vuelve extremadamente complejo. Cosas como recursos y SharedPreferences no son fáciles de burlar. Estos problemas se han abordado en API de terceros como Robolectric.

Te sugiero que uses Robolectric para tus pruebas unitarias de Android. Robolectric se ejecuta en una máquina virtual estándar (es decir, no se necesita emulador). Robolectric simula la mayor parte del sistema Android, minimizando (pero no eliminando) la necesidad de construir simulacros. Me ha parecido una herramienta muy útil para Android TDD.

2
EJK 25 ene. 2016 a las 21:16

Como segunda respuesta (y quizás más útil que la primera) te sugiero que dividas las lógicas de las dependencias de la plataforma.

De esta manera, puede considerar realizar una prueba unitaria de la lógica de una manera puramente java.

Eche un vistazo al patrón MVP. ¡Debería ayudar mucho!

En este caso, por ejemplo, movería esta línea ...

MyObjectService myService = new MyObjectService(getRequestHeaders(context), locale);

... dentro de un "Servicio" que es completamente una clase java pura asignada por un constructor que requiere (en este caso) un valor de cadena llamado "locale" y una estructura de datos llamada "encabezados"

Fácil, ¿no? ;)

Mis 2 centavos: cada vez que necesita Robolectric para probar la lógica (en lugar de la interfaz de usuario) probablemente cometa un error

0
Tommaso Resti 25 ene. 2016 a las 22:18

Utilice el entorno de ejecución de Robolectric

Locale locale = RuntimeEnvironment.application.getResources().getConfiguration().locale;
0
Tommaso Resti 25 ene. 2016 a las 22:06