2011-09-12 14 views
11

Estoy escribiendo algunas pruebas de POJO para mi código de Android.Probando el código de Android con JUnit y el JDK

Quiero ejecutarlos localmente con el JDK (no con Dalvik en el emulador) - por velocidad, JUnit 4, Mockito, y poder ejecutar sin cabeza sin un dispositivo - entonces tengo un proyecto "Java" separado en Eclipse.

Si el método que estoy probando ocurre hacer referencia a cualquier cosa, desde el SDK de Android, por ejemplo, android.util.Log, la prueba falla; esto tiene sentido porque android.jar no está en la ruta de clase. Para reproducir tengo este caso de prueba:

public class FooTests { 
    @Test 
    public void testFoo() { 
    android.util.Log.d("x", "y"); 
    } 
} 

Si añado android.jar explícitamente a la ruta de clase del proyecto de prueba, consigo excepciones como

java.lang.RuntimeException: Stub! 
    at android.util.Log.d(Log.java:7) 
    at com.example.FooTests.testFoo(FooTests.java:39) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    ... 
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

¿Hay una manera de hacer que el código sin burla a cabo cada último bit de la dependencia de Android SDK? Tal vez ya existe una android.jar falsa?

EDITAR: Por ahora me terminó envolviendo clases como android.util.Log e inyectarlas en los casos, para la prueba clásica basada en el COI. La sugerencia de PowerMock de Scott es mi próximo paso cuando lo necesite.

LATER EDIT: Robolectric!

Respuesta

3

No hay burlado a cabo android.jar que yo sepa. Yo uso Powermock para burlar todo. Una cosa que puedes hacer para ayudar con la burla pesada es hacer que tus clases ampliadas de Android como actividad, fragmentos, locutores, etc. sean delgadas y hacer que deleguen en clases de pojo. Podrías tomar una decisión basada en el riesgo para no aislar la unidad de prueba de las clases ampliadas de Android, y en su lugar, la unidad de integración probarlas a través del framework de pruebas de Android u otra cosa como Robotium.

Por cierto pruebas de unidad de aislamiento en Android, para mí la unidad de pruebas en la JVM de Java burlarse de todos a cabo todas las clases colaboradoras es el mejor camino a seguir.

+1

+1 Buenos puntos, probaré PowerMock. Todos los enlaces relevantes más allá de https://sites.google.com/site/androiddevtesting/? – orip

+1

No he visto ese enlace anteriormente, pero es excelente, Gracias por compartir. Me encuentro haciendo referencia a la sección de "uso" de Powermock en su sitio web con bastante frecuencia cuando trato de descubrir las diversas formas que se necesitan para burlarse de las clases de jar android: http://code.google.com/p/ powermock /. – Scott

0

¿No será the embedded android/junit tests hacer lo que quiere?

+4

Hasta ahora lo he usado para ejecutar pruebas con InstrumentationTestRunner en un emulador o en un dispositivo real. Es apropiado cuando quiero probar una actividad o un servicio, pero no cuando solo quiero probar alguna vieja lógica sin relación con la plataforma Android. ¿Me estoy perdiendo de algo? – orip

+0

Creo que la primera viñeta habla de las pruebas de "simple viejo junio", para su "vieja lógica simple" :) – KevinDTimm

+0

Claro, pero por lo que puedo decir, o bien tengo que ejecutarlos en un emulador o dispositivo, u obtener "Stub ! " excepciones igual que ahora :( – orip

4

Tuve el mismo problema. Quería probar POJOs simples localmente.
Específicamente, mi código quería usar android.util.Base64.
Lo que terminé haciendo fue utilizar el SDK para instalar las fuentes de Android 4, y copié la clase android.util.Base64 a mi proyecto.
Sorprendentemente, esto funcionó.

+0

Sí, terminé creando una interfaz tipo "Base64Encoder", implementándola con 'android.util.Base64' en la aplicación y con' sun.misc.BASE64Decoder' en las pruebas :) Hubiera sido increíble simplemente tener un JAR con todo el código de la biblioteca intacto, y solo los bits del framework que están vinculados a un entorno en ejecución anulado. – orip

2

que tenían el mismo problema. Quería probar lógica empresarial simple localmente. Específicamente, mi código usa android.util.SparseArray<E>.

me trataron 3 enfoques diferentes para que sea comprobable con JUnit fuera androide.

  • En mi lógica de negocio que crea una interfaz y unida a MySparseArray<E> que hereda de SparseArray<E>. En la prueba junit reimplecé la interfaz usando HashMap<Integer, E>. Esto funciona pero a la larga esto es mucho trabajo para hacer que la lógica de negocios sea comprobable por unidad si se requieren otros android.*.
  • Según lo sugerido por @Tal Weiss, agregué las fuentes android java de las clases requeridas: android.util.SparseArray.java que usa com.android.internal.util.ArrayUtils.java. Esto también funciona, pero no me gusta agregar más fuentes de Android, especialmente si hay muchas más dependencias
  • He descargado un código binario libre android.jar para un antiguo android 2.2 de http://grepcode.com/snapshot/repository.grepcode.com/java/ext/com.google.android/android/2.2_r1.1 y lo incluí como lib en mi junit-java -proyecto. Este archivo contiene solo clases para los espacios de nombres android.*, com.android.*, dalvik.* y framework.base.*. Esto también funciona

Actualmente lo logrado evitar el uso de las clases excepto android.*SparseArray<E> en mi capa de negocio y no tiene dependencia de contexto, la actividad o servicio. Podría haber usado HashMap<Integer, E> en la capa android-business en lugar de SparseArray<E>.

+0

He intentado con https://github.com/bjoernQ/unmock-plugin para usar SparseArray en las pruebas JUnit y funcionó, pero después de agregar keepStartingWith "dalvik.system". en la sección unMock. – Alexey

Cuestiones relacionadas