ActivityUnitTestCase arroja RuntimeException cuando se ejecuta con AndroidJUnitRunner
Estoy intentando integrar AndoridJUnitRunner de Espresso 2.0 con ActivityUnitTestCase. Sin embargo, mis pruebas se estropean cuando startActivity () intenta inicializar mMockParent = new MockParent () .
Esto es lo que hice:
- Robolectric buildActivity () con espía Mockito?
- Prueba de unidades de Android con ContentProviders
- Prueba de unidades de Android en Eclipse: "Error al iniciar la prueba"
- Pruebas de ejecución automática antes de la compilación de aplicaciones en Android Studio
- Prueba de AsyncTaskLoaders con Robolectric
Cree un nuevo proyecto con Intellij 14 CE y realice algunos cambios en build.gradle.
android{ defaultConfig { applicationId "com.noob.testing" minSdkVersion 9 targetSdkVersion 21 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } compileOptions { sourceCompatibility JavaVersion.VERSION_1_7 targetCompatibility JavaVersion.VERSION_1_7 } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile 'com.android.support:appcompat-v7:21.0.+' androidTestCompile('org.mockito:mockito-core:1.9.5') androidTestCompile('com.google.dexmaker:dexmaker:1.2') androidTestCompile('com.google.dexmaker:dexmaker-mockito:1.2') androidTestCompile('com.android.support.test.espresso:espresso-core:2.0') androidTestCompile('com.android.support.test:testing-support-lib:0.1') }
Escriba una prueba de unidad de estilo JUnit4.
@RunWith(AndroidJUnit4.class) public class MainActivityJUnit4Test extends ActivityUnitTestCase<MainActivity> { public MainActivityJUnit4Test() { super(MainActivity.class); } MainActivity activity; @Before public void setup() throws Exception { injectInstrumentation(InstrumentationRegistry.getInstrumentation()); super.setUp(); ContextThemeWrapper context = new ContextThemeWrapper(getInstrumentation().getTargetContext(), R.style.AppTheme); setActivityContext(context); activity = startActivity(new Intent(Intent.ACTION_MAIN), null, null); } @Test public void baseCase() { TextView tv = (TextView) activity.findViewById(R.id.tv); Assert.assertEquals("Hello World", tv.getText()); } }
Ejecute la prueba, obteniendo una traza de pila.
junit.framework.AssertionFailedError at junit.framework.Assert.fail(Assert.java:48) at junit.framework.Assert.assertTrue(Assert.java:20) at junit.framework.Assert.assertNotNull(Assert.java:218) at junit.framework.Assert.assertNotNull(Assert.java:211) at android.test.ActivityUnitTestCase.startActivity(ActivityUnitTestCase.java:147) at com.sdchang.testing.MainActivityJUnit4Test.setup(MainActivityJUnit4Test.java:32) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) at org.junit.runners.ParentRunner.run(ParentRunner.java:300) at org.junit.runners.Suite.runChild(Suite.java:128) at org.junit.runners.Suite.runChild(Suite.java:24) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) at org.junit.runners.ParentRunner.run(ParentRunner.java:300) at org.junit.runner.JUnitCore.run(JUnitCore.java:157) at org.junit.runner.JUnitCore.run(JUnitCore.java:136) at android.support.test.runner.AndroidJUnitRunner.onStart(AndroidJUnitRunner.java:270) at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1701)
Este rastro de pila es en realidad un
java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare()
Que se produce cuando startActivity () intenta inicializar mMockParent = new MockParent () :
ComponentName cn = new ComponentName(mActivityClass.getPackage().getName(), mActivityClass.getName()); intent.setComponent(cn); ActivityInfo info = new ActivityInfo(); CharSequence title = mActivityClass.getName(); mMockParent = new MockParent(); String id = null;
¿Estoy perdiendo algo más para que AndroidJUnitRunner funcione con ActivityUnitTestCase? Cualquier ayuda sería muy apreciada.
- Archivo de cobertura de código Jacoco vacío que conduce a informes de cobertura falsa
- Ejecución de pruebas unitarias antes de cada construcción en Gradle
- Cómo deshabilitar las pruebas de unidad de estudio de Android (androidTest)
- Configuración de un directorio de activos personalizados para las pruebas unitarias en Android Studio
- Prueba de la unidad de Android Studio SQLiteDataBase es nula
- Soporte de la clase Robolectric de Android. Cómo tener las referencias de la clase de biblioteca R desde el proyecto de aplicación
- Cómo correctamente mock HttpGet llamada en la prueba de Android
- Enviar Tecla Intro usando robotium para pruebas de Android?
Después de golpear mi cabeza contra la pared, ventanas y varios muebles, finalmente conseguí mis pruebas de trabajo!
A partir de una respuesta en su seguimiento de problemas , aprendí que no se pueden crear nuevos Handlers desde el hilo de instrumentación. Lo que significa startActivity () debe ser invocado en el subproceso de la interfaz de usuario. Lo que lleva a 3 soluciones.
1.Use Instrumentation's runOnMainSync()
getInstrumentation().runOnMainSync(new Runnable() { @Override public void run() { activity = startActivity(new Intent(Intent.ACTION_MAIN), null, null); } });
2.Create su propia clase base que extiende ActivityUnitTestCase y reemplazar startActivity
@Override protected T startActivity(final Intent intent, final Bundle savedInstanceState, final Object lastNonConfigurationInstance) { return startActivityOnMainThread(intent, savedInstanceState, lastNonConfigurationInstance); } private T startActivityOnMainThread(final Intent intent, final Bundle savedInstanceState, final Object lastNonConfigurationInstance) { final AtomicReference<T> activityRef = new AtomicReference<>(); final Runnable activityRunnable = new Runnable() { @Override public void run() { activityRef.set(YourBaseActivityUnitTestCase.super.startActivity( intent, savedInstanceState, lastNonConfigurationInstance)); } }; if (Looper.myLooper() != Looper.getMainLooper()) { getInstrumentation().runOnMainSync(activityRunnable); } else { activityRunnable.run(); } return activityRef.get(); }
3. Si llama a startActivity () en un método de prueba y toda su prueba puede ejecutarse en el hilo principal, simplemente puede anotar su método de prueba con @UiThreadTest.
En mis pruebas, he probado todas las 3 soluciones, pero solo 1 & 2 funcionará .
- ¿Cómo ejecutar mi código Go en Android?
- Cómo puedo descargar imágenes de google play developer console