Obtenga la actividad actual en la prueba de instrumentación de Android

Mi MainActivity en mi aplicación de Android comprueba si el usuario está conectado (esto se almacena en SharedPreferences) y si no lleva al usuario a LoginActivity. Estoy intentando probar esto usando el código siguiente

public class MainActivityTest extends ActivityInstrumentationTestCase2<MainActivity> { private static final int TIME_OUT = 5000; /* miliseconds */ private MainActivity mMainActivity; private Instrumentation mInstrumentation; private SharedPreferences mLoginPrefs; public MainActivityTest() { super(MainActivity.class); } protected void setUp() throws Exception { super.setUp(); setActivityInitialTouchMode(false); mMainActivity = getActivity(); mInstrumentation = getInstrumentation(); mLoginPrefs = mInstrumentation.getTargetContext().getSharedPreferences(LoginActivity.PREFS_NAME, Context.MODE_PRIVATE); SharedPreferences.Editor editor = mLoginPrefs.edit(); // User is not logged in, so it should be redirect to LoginActivity editor.putBoolean("logged_in", false); editor.commit(); } //... public void testC_OpenLoginActivityIfUserIsNotLoggedIn() { ActivityMonitor monitor = mInstrumentation.addMonitor(LoginActivity.class.getName(), null, false); Activity nextActivity = mInstrumentation.waitForMonitorWithTimeout(monitor, TIME_OUT); assertNotNull(nextActivity); nextActivity.finish(); SharedPreferences.Editor editor = mLoginPrefs.edit(); // Login the user so we can continue the tests editor.putBoolean("logged_in", true); editor.commit(); } 

Pero esto no funciona, LoginActivity se abre, pero waitForMonitorWithTimeout nunca vuelve, así que me quedé atascado en LoginActivity (Necesito volver a MainActivity para hacer las otras pruebas).

Un código similar a esta Pregunta SO funciona para los clics del botón, pero esta actividad no está cargada por ningún clic, así que estoy pensando que tal vez no hay tiempo para que el monitor funcione.

Sólo necesito una forma de obtener la Actividad real para poder hacer una afirmación y hacer que termine de continuar mis pruebas.

Sólo otra cosa: Preferiría un método sin usar Robotium si es posible.

Con el fin de resolver su problema, primero eche un vistazo a los dos métodos más importantes para su prueba:

 Instrumentation#addMonitor(java.lang.String, android.app.Instrumentation.ActivityResult, boolean) Instrumentation.ActivityMonitor#waitForActivity() 

Según la referencia de la API de Android:

addMonitor

Agregue un nuevo Instrumentation.ActivityMonitor que se verificará cada vez que se inicie una actividad . El monitor se añade después de los existentes; el monitor será golpeado sólo si ninguno de los monitores existentes pueden manejar el intento.

waitForActivity

Bloquear hasta que se cree una actividad que coincida con este monitor, devolviendo la actividad resultante.


Ahora dejémoslo un poco más claro.

addMonitor debe ser llamado siempre antes de que se inicie la actividad esperada, nunca demasiado tarde.

waitForActivity debe ser llamado sólo después de que se inicie la actividad esperada, nunca demasiado temprano, ya que bloqueará.


Volver a su código:

Están llamando a ambos juntos, sin que nada mágico suceda entre ellos. Por lo tanto, es demasiado tarde para addMonitor, o demasiado pronto para waitForActivity.

 ActivityMonitor monitor = mInstrumentation.addMonitor(LoginActivity.class.getName(), null, false); Activity nextActivity = mInstrumentation.waitForMonitorWithTimeout(monitor, TIME_OUT); 

Si es demasiado pronto para llamar a waitForActivity, bloqueará y fallará hasta el tiempo de espera (porque la actividad esperada aún no se ha alcanzado) y nunca vería la actividad esperada iniciada.

Si es demasiado tarde para llamar a addMonitor, el monitoreo comienza después de que se inicie la actividad esperada, y la actividad esperada no se vuelve a iniciar desde entonces, por lo que waitForActivity se bloqueará debido a que no se ha alcanzado el monitor.

Así que la diferencia entre los dos casos es si la actividad esperada se inicia o no . Y para tu caso, creo que es demasiado tarde para llamar a addMonitor.

La solución es muy sencilla: basta con mover addMonitor a una posición suficientemente temprana antes de que inicie LoginActivity, tal vez moverlo al método setUp , como esto:

 mInstrumentation = getInstrumentation(); ActivityMonitor monitor = mInstrumentation.addMonitor(LoginActivity.class.getName(), null, false); 

BTW, para su caso, con tiempo de espera o sin tiempo de espera no importa.

No se olvide de quitar el monitor después de que no es necesario más eg:

 @Override protected void tearDown() throws Exception { mInstrumentation.removeMonitor(monitor); super.tearDown(); } 

Estabas en el buen camino. El método que debe llamar es:

 monitor.waitForActivityWithTimeout(TIME_OUT); 

en lugar de

 mInstrumentation.waitForMonitorWithTimeout(monitor, TIME_OUT); 
  • ¿Es posible que un método de devolución de llamada se llame después de onDestroy?
  • TimerTask vs Thread.sleep vs Handler postDelayed - más preciso para llamar a la función cada N milisegundos?
  • No se puede instanciar actividad- ClassNotFoundException
  • android obtener la fecha anterior de una fecha correspondiente (no la fecha de ayer)
  • Cómo encontrar el código fuente de la llamada de función nativa de Java
  • Obtener el tamaño del archivo en android sdk?
  • GetLastNonConfigurationInstance devuelve siempre null
  • NullPointerException en CustomArrayAdapter
  • Emitir mensajes socket.io en Android
  • Agregar una cookie a una solicitud HTTP
  • Clasificación de ListView por nombre del producto con adaptador personalizado?
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.