2012-03-14 9 views
6

Mi prueba se centra en una AsyncTask completando y validando que se inicia una actividad posterior.ActivityUnitTestCase y Activity # runOnUiThread

Se sabe que AsyncTask # onPostExecute no se invoca a menos que el AsyncTask se instancia y se ejecuta desde el hilo de interfaz de usuario, por lo que mi método (prueba visible) para invocar el AsyncTask pasa a través de las precauciones necesarias para asegurar este comportamiento - a través de un Ejecutable que se ejecuta inmediatamente si está en el hilo de UI o está programado para ejecutarse en el hilo de UI.

Cuando se invoca este método desde una prueba ActivityUnitTestCase, Runnable que crea una instancia y ejecuta esta AsyncTask mediante Activity # runOnUiThread termina ejecutándose en una hebra que no sea la hebra de la IU. ¿Hay alguna forma de garantizar que Runnable se ejecute en el subproceso de interfaz de usuario dentro de la actividad?

Adenda:

  • la prueba se ejecuta como se esperaba bajo un clase ActivityInstrumentationTestCase2, pero no tienen acceso a ActivityUnitTestCase # getStartedActivityIntent. Soy consciente de Instrumentation.ActivityMonitor y no es una solución.
  • Runnables programados en ActivityUnitTestCase # runTestOnUiThread do ejecutar en la interfaz de usuario thread.
  • No estoy buscando redefinir mi prueba.
  • Por extraño que parezca, ActivityUnitTestCase # startActivity llama Activity # onCreate NOT al subproceso de la interfaz de usuario.

Editar: Aquí hay un poco de código (no probado) que demuestra la esencia del problema:

// ExampleActivityTests.java 

class ExampleActivityTests : public ActivityUnitTestCase <ExampleActivity> { 

    public void testThatRequiresUiThread() { 

     startActivity (new Intent(), null, null); 
     // ...call instrumentation onStart, onResume... 

     runTestOnUiThread(new Runnable() { 
      public void run() { 
       boolean isUiThread = Thread.currentThread() == Looper.getMainLooper().getThread(); 
       Log.d ("A", "Running on UI Thread? " + isUiThread); 
      } 
     }); 

     getActivity().methodRequiringUiThread(); 

     // assertions here... 
    } 
} 

// ExampleActivity.java -- just the relevant method 

    public void methodRequiringUiThread() { 

     runOnUiThread(new Runnable() { 
      public void run() { 
       boolean isUiThread = Thread.currentThread() == Looper.getMainLooper().getThread(); 
       Log.d ("B", "Running on UI Thread? " + isUiThread); 
      } 
     }); 
    } 

En LogCat veremos:

A | Running on UI Thread? true 
B | Running on UI Thread? false 
+1

Un poco confundido por la lectura de sus declaraciones _ "a través de un Ejecutable que se ejecuta inmediatamente si en el hilo de interfaz de usuario o está programado para ejecutarse en el subproceso de interfaz de usuario" _, mejor para adjuntar algún fragmento de código para aclarar su problema – yorkw

+0

Tal vez esa afirmación estaba detallando demasiado la implementación; su propósito era simplemente llevar a casa que estoy de hecho asegurándome de que AsyncTask se crea y ejecuta en el hilo de la interfaz de usuario. Puedo agregar un código que demuestre el problema que estoy enfrentando, pero lo haré con este aspecto omitido. – Travis

Respuesta

4

Calling ActivityUnitTestCase # startActivity en el hilo de la interfaz de usuario resuelve mi problema.

public void testThatRequiresUiThread() { 

    runTestOnUiThread(new Runnable() { 

     @Override 
     public void run() { 
      startActivity(new Intent(), null, null); 
     } 
    }); 

    // ... 
    getActivity().methodRequiringUiThread(); 

    // rest of test... 
} 

produce

A | Running on UI Thread? true 
B | Running on UI Thread? true